android application回收
原创
©著作权归作者所有:来自51CTO博客作者钰娘娘ynn的原创作品,请联系作者获取转载授权,否则将追究法律责任
前段时间因为加了个定位保存功能,需要用到Sqlcipher,这个要在application做初始化。结果各种机器总莫名错误,好郁闷T T。老大说是application被回收了,叫我在onCreate里面根据权限初始化的内容去掉,直接初始化,于是,我有了疑问:回收以后的application难道还会调用onCreate?
于是各种查资料,发现答案是:不会!但因为数据本身是在application当中,仍然有可能被回收!你可以使用galaxy模拟器来试一试。
那么,怎么解决application回收初始化数据的问题呢?
思路1:如果Application有类似activity的生命周期,问题就容易解决。application的生命周期是什么样的?
以下有关生命周期的部分摘自:
public class App extends Application
@Override
public void onCreate() {
// 程序创建的时候执行
Log.d(TAG, "onCreate");
super.onCreate();
}
@Override
public void onTerminate() {
// 程序终止的时候执行
Log.d(TAG, "onTerminate");
super.onTerminate();
}
@Override
public void onLowMemory() {
// 低内存的时候执行
Log.d(TAG, "onLowMemory");
super.onLowMemory();
}
@Override
public void onTrimMemory(int level) {
// 程序在内存清理的时候执行
Log.d(TAG, "onTrimMemory");
super.onTrimMemory(level);
}
}
结果:
打开Activity
08-16 15:16:27.142: D/CARLOZ - Application(28202): onCreate
08-16 15:16:27.172: D/CARLOZ - MainActivity3(28202): onCreate
08-16 15:16:27.232: D/CARLOZ - MainActivity3(28202): onStart
08-16 15:16:27.232: D/CARLOZ - MainActivity3(28202): onResume
HOME键退出应用程序
08-16 15:16:55.372: D/CARLOZ - MainActivity3(28202): onPause
08-16 15:16:55.942: D/CARLOZ - MainActivity3(28202): onStop
08-16 15:16:55.952: D/CARLOZ - Application(28202): onTrimMemory 回收内存
重新打开应用程序
08-16 15:17:20.962: D/CARLOZ - MainActivity3(28202): onRestart
08-16 15:17:20.962: D/CARLOZ - MainActivity3(28202): onStart
08-16 15:17:20.962: D/CARLOZ - MainActivity3(28202): onResume
长按MENU键,打开Recent TASK
08-16 15:17:28.972: D/CARLOZ - MainActivity3(28202): onPause
08-16 15:17:28.992: D/CARLOZ - MainActivity3(28202): onStop
08-16 15:17:29.022: D/CARLOZ - Application(28202): onTrimMemory
彻底关闭应用程序
08-16 15:17:31.542: D/CARLOZ - MainActivity3(28202): onDestroy
可见,application本身只有onCreate提供给我们, onTrimMemory要求android版本>=14,有版本要求,而且也没有恢复方法,真心无语。。。
思路2:曲线救国,启动Activity时间接更新application
要知道应用启动的时候会调用onResume(),那么,我要用这个来重新初始化被回收的application数据吗?想了一下,还是决定不要用它,因为onResume()进行过多操作会导致界面阻塞,用户体验不好,比较好的是用onWindowFocusChanged(boolean)当为true时,界面一定加载在前台。另外要在BaseActivity里面写,这样大概每个类都用的到:
第一步:自定义application:MyApp
<application
android:allowBackup="true"
android:name=".MyApp"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
</application>
public class MyApp extends Application
private boolean initedDatas = false;
@Override
public void onCreate() {
super.onCreate();
initDatas();
}
public void initDatas() {
initedDatas = true;
Log.i("MyApp","inited");
//初始化
}
public boolean isInitedDatas(){
return
注意把初始化的数据全部扔进initDatas()这个方法,这里特意设了一个initedDatas,作用是:回收时会被回收,重新初始化为false。所以可以利用这一点来判断。
第二步:创建BaseActivity,所有Activity继承它
public class BaseActivity extends AppCompatActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
MyApp app = (MyApp) getApplicationContext();
if(hasFocus && !app.isInitedDatas()){
app.initDatas();
}
}
}
public class MainActivity extends BaseActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
每当应用获取焦点的时候,会调用:onWindowFocusChanged(true),此时,如果application是被回收的(initedDatas为false),则恢复application数据。