一、背景

        我们在使用android app的过程中,可能突然会遇到其他的事情需要将app退到后台,比如微信来了一条消息需要回复,当我们回复完消息在切换回我们的app时,如果处理不好,应用可能会白屏或者闪退。造成这种现象的原因,是android的进程回收机制,android会给每一个应用分配一定的内存,当应用退入后台时,系统并不会将应用杀死,而是将应用缓存起来。打开的应用越多,后台缓存的进程也越多,那么占用的内存也越大,当系统内存不足时,就会根据自己的一套进程回收机制去杀死应用,以便腾出内存空间来分配给其他的应用,后面会详细分析android的进程回收机制。也就是说,当我们将应用退入后台后,应用很可能会因为系统内存不足而被杀死,应用被杀死后,所有的Activity都被销毁了,但是Android也提供了一定的补救措施,activity棧并没有被清空,也就是说如果之前的Activity棧中的内容是A-->B-->C,只是ABC这三个Activity的对象被销毁了,当我们切换应用时,系统首先会重新创建Activity C,由于需要重新创建Activity实例,需要耗费一点时间,所有会有短暂的白屏现象。另外当Activity被意外杀死时,Android会调用Activity的onSaveInstance让开发者去保存应用的数据,在重新创建Activity时,会调用onRestoreInstanceState来恢复应用数据,但是针对大量需要恢复的数据,一旦处理不当,就有可能造成应用闪退,比如,应用在后台被杀死后,所有的静态变量都会被清空,这个时候我们如果直接使用这些静态变量,就会报空指针异常,从而造成程序闪退。


二、解决办法

       针对需要恢复的数据比较少的应用,我们可以通过Activity的onSaveInstance和onRestoreInstanceState去恢复,针对静态变量比较多的情况,我们可以考虑采用数据持久化的方式,所有的静态对象都改为单例模式,然后附加上一些持久化cache,空了再取缓存。嗯,这肯定也是一个办法,但是这样的束手束脚对开发来说也是痛苦,一旦处理漏了就会发生空指针异常。我们能不能换一种思路来解决上面的问题,当应用在后台被杀死时,不做Activity棧的恢复,清空Activity棧,并且直接启动应用的第一个Activity,一般是欢迎界面,这样的话,应用就相当于重启了一次,所有的逻辑都会重新开始,也就不存在静态变量为空的问题了,目前很多应用都是这样处理的。那么我们如何判断应用已经被杀死并重新创建了呢?因为静态变量的生命周期和应用的生命周期是一致的,应用被杀死后,静态变量会被回收掉,重新启动静态变量的数据会重新初始化,可以考虑定义在应用中定义一个静态变量,初始值为0,在应用的第一个界面的onCreate方法中将静态变量设置为1,表示应用走的是正常的启动流程,然后写一个基类的BaseActivity,其他的Activity都继承BaseActivity,在BaseActivity的onCreate方法中判断静态变量的值是否为1,如果不为1,则表示应用不是通过正常的流程启动的,则清空Activity棧,并启动第一个Activity。具体代码如下:

package com.liunian.androidbasic;import android.app.Application;import android.content.Context;import android.content.Intent;/** * Created by dell on 2018/4/13. */public class App extends Application {    public final static int APP_STATUS_KILLED = 0; // 表示应用是被杀死后在启动的    public final static int APP_STATUS_NORMAL = 1; // 表示应用时正常的启动流程    public static int APP_STATUS = APP_STATUS_KILLED; // 记录App的启动状态    private static Context context;    @Override    public void onCreate() {        super.onCreate();        context = getApplicationContext();    }    public static Context getAppContext() {        return context;    }    /**     * 重新初始化应用界面,清空当前Activity棧,并启动欢迎页面     */    public static void reInitApp() {        Intent intent = new Intent(getAppContext(), SplashActivity.class);        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);        getAppContext().startActivity(intent);    }}

package com.liunian.androidbasic;import android.content.Intent;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;/** * 启动欢迎页面 */public class SplashActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        App.APP_STATUS = App.APP_STATUS_NORMAL; // App正常的启动,设置App的启动状态为正常启动        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_splash);        goMain();    }    /**     * 去主页面     */    private void goMain() {        Intent intent = new Intent(SplashActivity.this, MainActivity.class);        startActivity(intent);        finish();    }}
package com.liunian.androidbasic.base;import android.os.Bundle;import android.support.annotation.Nullable;import android.support.v7.app.AppCompatActivity;import android.util.Log;import com.liunian.androidbasic.App;/** * Created by dell on 2018/4/17. * 用来处理应用在后台被杀死后,让应用重新走启动流程 */public abstract class BaseActivity extends AppCompatActivity {    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        if (App.APP_STATUS != App.APP_STATUS_NORMAL) { // 非正常启动流程,直接重新初始化应用界面            Log.i("liunianprint:", "reInitApp");            App.reInitApp();            finish();            return;        } else { // 正常启动流程            setUpViewAndData(savedInstanceState); // 子Activity初始化界面        }    }    /**     * 提供给子Activity设置界面的接口,不要在onCreate中初始化界面     * @param savedInstanceState     */    protected abstract void setUpViewAndData(@Nullable Bundle savedInstanceState);}

这里需要注意一点,继承BaseActivity的Activity初始化界面不要在onCreate中处理,而应该在setUpViewAndData处理,因为在onCreate方法中静态变量可能为空,而只有应用时正常启动时,才会调用setUpViewAndData方法。

三、总结

1、Android系统会为每一个应用分配一定的内存,当系统内存不足时,Android系统会按照进程回收机制来杀死一部分应用,并回收内存提供给其他的应用;

2、应用被系统杀死后,应用中所有的数据都会被回收掉,但是Activity提供了一定的补救措施,应用中的Activity棧还是会保存下来,并且提供了onSaveInstance和onRestoreInstanceState来恢复界面数据,因为需要重新创建Activity对象,需要耗费一定时间,所以可能会有短暂的白屏现象;

3、面对大量要恢复的数据(特别是静态变量),如果我们采用恢复数据的方式来处理应用被系统杀死的问题,代码将会很复杂,我们必须非常小心的处理数据恢复的问题,并且数据恢复也存在一定的效率问题,毕竟需要将数据持久化;

4、针对应用被杀死的问题,可以采用重新初始化应用流程的方式来解决,也就是如果发现应用时非正常启动,则清空当前Activity棧,并且去启动应用的欢迎界面,这样就相当于重新打开应用一样,这种处理方式虽然没有应用被杀死前的数据,但是处理起来简单方便。


附上源码:https://github.com/2449983723/AndroidComponents



更多相关文章

  1. Android(安卓)API Guides---Near Field Communication
  2. Android高效率编码-第三方SDK详解系列(二)——Bmob后端云开发,实
  3. Android编译错误:You have tried to change the API from what ha
  4. (Android(安卓)Studio)Android(安卓)手机设备与HC05 蓝牙设备的
  5. mvp过渡到mvvm(Android(安卓)架构组件)
  6. android存储之网络存储和数据库存储
  7. Android上实现柱状图表
  8. 搭建Android应用程序的服务器
  9. android studio生成JKS时候提示:JKS 密钥库使用专用格式。建议使

随机推荐

  1. Android群英传知识点回顾——第五章:Andro
  2. Android中进程间通讯 AIDL
  3. Android新架构组件之Navigation
  4. Android学习记录——1.Android Studio
  5. Android(安卓)属性: persist
  6. TabHost,TabWidget区别总结
  7. android Android开发环境搭建
  8. Android 中文 API (17) ―― TextSwitcher
  9. Xamarin for Android/IOS离线安装说明
  10. Android音频系统之AudioTrack