当我的应用程序启动时,我在一个hashmap中加载来自服务器的所有字符串数据,并从该hashmap读取所有屏幕,以显示按钮名称,文本和屏幕标题.
我依靠这个对象(以及许多其他类似对象)的生命来维持我的应用程序保持功能.
我发现,如果我在几个小时后恢复应用程序,它仍然可以正常运行.但是,如果我再打开10个应用程序,让它们全部打开并在几个小时后恢复应用程序,它会尝试从其中一个对象中读取,但它们现在已经消失了!
在这些情况下,我发现最好杀死应用程序并重新启动它,并尝试在主要活动的onDestroy中这样做,但这是因为我切换到另一个活动5秒后调用了上一个活动的onDestroy并且app使用此代码被杀死:
android.os.Process.killProcess(android.os.Process.myPid());
Run Code Online (Sandbox Code Playgroud)
因此,我只想在闲置数小时并且资源无效时杀死应用程序.这样,当用户尝试恢复它时,它将死亡并再次启动,从而再次将所有资源加载到存储器中.
我在Application类中查找了一个onDestroy方法,但没有一个.Thre是onTrimMemory方法.
问题是:
如何使用Application.onTrimMemory()回调来终止我的应用程序它所需的资源已被销毁?
编辑:实际上,阅读onTrimMemory文档,我留下的印象是它应该通过销毁对象释放内存,如果我不这样做,那么为什么在恢复应用程序后,这些对象现在为空?我不懂.
EDIT2:
我设法部分解决了我的问题:
我从Google下载了一个"Fill Ram"应用程序,该应用程序是为想要了解他们的应用程序在低内存情况下的行为的开发人员而制作的
我逐渐开始填充ram并看到onTrimMemory方法是如何使用值或分别为20,40,60和80调用的
每次我看到它在日志中被调用后我迅速恢复了我的应用程序然后在60或80左右,我需要的资源是null
我在onResume中插入了一个空指针检查,如果这些资源为null,我执行了以下操作:
if (application.data == null || application.data.size() == 0) {
// Restart app so data is reloaded
Log.e("kill app", "kill app");
Intent mStartActivity = new Intent(this,MainActivity.class);
int mPendingIntentId = 123456;
PendingIntent mPendingIntent = PendingIntent.getActivity(this, mPendingIntentId, mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager mgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
System.exit(0);
}
Run Code Online (Sandbox Code Playgroud)
正如这里指出的:
这个问题仍然是半解决的,因为我想在我的应用程序中的某些其他地方可能会丢失一些其他资源,所以我正在考虑在onTrimMemory 60或80中执行此操作?
我需要更多帮助才能理解这一点.
另外,我应该使用
System.exit(0);
Run Code Online (Sandbox Code Playgroud)
要么
android.os.Process.killProcess(android.os.Process.myPid());
Run Code Online (Sandbox Code Playgroud)
我还做了其他的事情:
在我的基本活动中,所有其他活动都延伸,我添加了以下内容:
@Override
public void onTrimMemory(int …Run Code Online (Sandbox Code Playgroud) 我需要以编程方式重新启动应用程序.我的启动器活动称为" 登录 ",登录后,主要活动称为" 主要 ".在主要活动中,我想重新启动应用程序.所以我有以下内容:
Intent i = getBaseContext().getPackageManager().getLaunchIntentForPackage(getBaseContext().getPackageName());
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
Run Code Online (Sandbox Code Playgroud)
这将显示"登录"活动,但是当我按下时,我将返回上一个活动.
有没有更好的方法来真正重启应用程序?
所以,我现在正面临这个奇怪的问题。我HAVE使用SharedPreferences.Editor()。提交()在我的Android应用程序,但是,因为文档在这里指出,
由于SharedPreferences实例是流程中的单例,因此如果您已经忽略了返回值,则可以安全地用apply()替换任何commit()实例。
您无需担心Android组件的生命周期及其与apply()写入磁盘的交互。该框架确保在切换状态之前完成对apply()的运行中磁盘写入。
基本上commit(),apply()如果您不使用返回值BUT,则可以安全地替换为BUT,这是这里提到的两者之间的区别,并且在Android Studio中警告说,这是commit()立即写入数据,而BUT apply()异步执行。
所以我的问题是,我正在更改应用程序中的语言,并且要在用户选择语言后重新启动应用程序。但是,当用户选择语言时,将输入当前选择的语言SharedPreferences。
现在,问题是:
每当我使用代码apply()代替此处commit()的代码并重新启动应用程序以在此处重新启动应用程序时,所做的更改都不会写入磁盘,因为当应用程序重新启动时,它不会更改当前语言,因为from的值SharedPreference不会更改,因为它不会立即写入磁盘。但是,无论何时使用commit(),更改都会立即写入,并且在重新启动应用程序后会成功更改语言。
因此,问题是:
如果有很大的不同,编写代码commit()并apply()声明使用apply()而不是完全安全的人会立即写出数据,但是会在后台执行呢?commit()commit()apply()
如果我构建了apk,如果我不使用返回值,它将在代码优化中commit()被替换apply()(我知道我可以通过构建应用程序的发行版来知道这一点,但是我仍然不确定,因为当我使用apply()veerery 时,它通常会更改1/10次,但确实会从SharedPreference更改值
一张纸条:
我试图在我的应用程序中提供一个选项,供用户擦除所有数据并重新开始.我已经尝试过一些东西,但似乎没有一个在数据仍然存在的意义上工作.这是我的第一次尝试:
public void clearDatabase(Context context) {
DatabaseHelper helper = new DatabaseHelper(context);
SQLiteDatabase database = helper.getWritableDatabase();
database.delete(Constants.TRANSACTION_TABLE, null, null); //erases everything in the table.
database.delete(Constants.CUSTOMER_TABLE, null, null);
database.delete(Constants.RETAILER_TABLE, null, null);
database.close();
}
Run Code Online (Sandbox Code Playgroud)
这似乎工作,但然后应用程序将重新启动时崩溃.
然后我在SQliteOpenHelper子类中尝试这个
public void resetDatabase() {
SQLiteDatabase database = getWritableDatabase();
database.execSQL("DROP TABLE IF EXISTS customer_table");
database.execSQL("DROP TABLE IF EXISTS transaction_table");
database.execSQL("DROP TABLE IF EXISTS retailer_table");
database.execSQL(CREATE_CUSTOMER_TABLE);
database.execSQL(CREATE_TRANSACTION_TABLE);
database.execSQL(CREATE_RETAILER_TABLE);
database.close();
}
Run Code Online (Sandbox Code Playgroud)
这不会在重新启动时崩溃,但数据仍然存在.唯一有效的是我以编程方式更改版本号.但是当我从IDE运行应用程序时,它将具有较旧的版本号,并且应用程序将无法启动,因为设备上的版本号高于代码中的版本号.
我还能尝试什么?