感谢这位哥的思路。

这个问题很常见,基本所有app都会遇到这个问题。但是很多开发者都没有处理。

问题的起因:我的app在进入后台后一段时间,可能被系统干掉了,然后通过多任务键,或者图标再点进去操作,出现xxId为null

经过一番探索发现:

app在被系统干掉后,重新进入,是会实例出所有的界面(因为他们都重写了onsaveInstance方法),但是这个界面所有的变量都变为null了(如果没有自己保存的话)。

解决的办法2种

1.每个页面都去重写onsaveInstace方法,去保存数据(对于老项目来说,这个工程量是非常巨大的)(如果是新项目,建议用一个好的框架,统一处理每一个页面变量的存取)

2.比较取巧的办法就是在被干掉重启的时候,重新进入SplashActivity(也就是启动页)。重走一遍流程,数据也就肯定不会出错了(ios系统上,如果出现被系统干掉的情况,也是采用的这种方法)

本文主要就是介绍第二种办法:

原理:

1.在splashActivity的oncreate时候就设置一个全局的变量值。

2.在baseActivity的oncreate中比较这个变量值是否发生变化(app在后台被干掉后重进,该值会变为默认)

3.如果发生了改变,就重进splashActivity,如果没有就正常处理

工具类一个:

/**
 * 这个类的作用是保证app进入后台被系统回收之后,再次进入app时重首页进入。
 * 配合splashactivity和baseactivity使用
 */
public class RestartUtils {
    public static final int STATUS_FORCE_KILLED = -1;//应用在后台被强杀了
    public static final int STATUS_NORMAL = 2; //APP正常态
    public static final String START_LAUNCH_ACTION = "start_launch_action";

    private int appStatus = STATUS_FORCE_KILLED; //默认为被后台回收了

    private static RestartUtils appStatusManager;

    public static RestartUtils getInstance() {
        if (appStatusManager == null) {
            appStatusManager = new RestartUtils();
        }
        return appStatusManager;
    }

    public int getAppStatus() {
        return appStatus;
    }

    public void setAppStatus(int appStatus) {
        this.appStatus = appStatus;
    }

}

BaseActivity里面:

@Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        switch (RestartUtils.getInstance().getAppStatus()) {
            case STATUS_FORCE_KILLED:
                Log.d("thisttt" , "BaseModuledActivity-STATUS_FORCE_KILLED");
                restartApp();
                break;
            case STATUS_NORMAL:
                Log.d("thisttt" , "BaseModuledActivity-STATUS_NORMAL");
                break;
            default:
                break;
        }
    }

    private void restartApp() {
        Intent intent = new Intent(this,MainActivity.class);
        intent.putExtra(START_LAUNCH_ACTION,STATUS_FORCE_KILLED);
        startActivity(intent);
    }

SplashActivity里面:

@Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        RestartUtils.getInstance().setAppStatus(STATUS_NORMAL);
        Log.d("thisttt" , "SplashActivity-setAppStatus");
        super.onCreate(savedInstanceState);
    }

注意事项有3点:

1.所有的activity包括SplashActivity都需要继承BaseActivity

2.SplashActivity的onCreate中,先设置setAppStatus()。再super.onCreate().

3.首页activity必须singtask(首页activity一般是SplashActivity下一个页面。具体看自己是否免登陆,免登陆就是MainActivity。不免登陆就是LoginActivity)

测试(模拟内存不足,被系统干掉):

很多帖子说用开发者模式的 不保留活动测试,是错误的。下面介绍不保留活动的特效

  • 保留app内存数据(全局的单例等),
  • 保留activity堆栈数据,
  • 再次开启app,会调用onCreate()重新创建栈顶的activity,

所以内存数据还是在的。

正确的办法是开发者模式->后台进程数限制->2个进程->然后开几个其他应用,你的应用就被干掉了。