Android项目长时间在后台运行后,再次打开程序崩溃问题完美解决(APP在后台被系统回收后,如何重新启动)

问题:

           因为手机内存不足的时候,会回收一些app,如果被回收的app中有全局变量,那么再次进入这个app就会出现异常报错。

 

原因:

          因为Application是全局变量,内存不足的时候会被回收,这个时候如果不是重启而是恢复之前的页面,系统会重新new 一个Application,所以没回收之前保存在Application中的信息都将没有了,这个时候被恢复的页面就可能因为需要Application中的信息报NullPointerException错。

         这说明:系统回收app后,再次进入此软件,Android只是恢复这个应用,并不是重启,它会创建一个新的Application对象并且启动上次用户离开时的activity以造成这个app从来没有被kill掉得假象。


What is Application
Application和Actovotu,Service一样是android框架的一个系统组件,当android程序启动时系统会创建一个 application对象,用来存储系统的一些信息。通常我们是不需要指定一个Application的,这时系统会自动帮我们创建,如果需要创建自己 的Application,也很简单创建一个类继承 Application并在manifest的application标签中进行注册(只需要给Application标签增加个name属性把自己的 Application的名字定入即可)。

android系统会为每个程序运行时创建一个Application类的对象且仅创建一个,所以Application可以说是单例 (singleton)模式的一个类.且application对象的生命周期是整个程序中最长的,它的生命周期就等于这个程序的生命周期。因为它是全局 的单例的,所以在不同的Activity,Service中获得的对象都是同一个对象。所以通过Application来进行一些,数据传递,数据共享 等,数据缓存等操作。


解决方法:

       看了大多数都是使用onSaveInstanceState和onRestoreInstanceState来保存UI状态的,基本上就是在按home键或者其他情况的时候存储数据,然后再次点开APP的时候读取bundle的数据,因为一般项目都有多个activity,这样做就比较麻烦了。

       这里将一个简单粗暴的方法:activity加载布局之前判断当前程序是否被系统回收,如果是则重新启动app。

       

具体代码如下:

1.创建 ——一个类保存app是否被回收的两个静态变量。

public class AppStatus {
    public static final int STATUS_RECYCLE =-1; //被回收
    public static final int STATUS_NORMAL=1;    //正常
}

 

2.创建——AppStatus的管理类,并初始appStatus(APP状态 )的值为被系统回收

public class AppStatusManager {
    public int appStatus = AppStatus.STATUS_RECYCLE;//APP状态 初始值被系统回收

    public static AppStatusManager appStatusManager;

    private AppStatusManager(){}

    //单例模式
    public static AppStatusManager getInstance() {
        if (appStatusManager == null) {
            appStatusManager = new AppStatusManager();
        }
        return appStatusManager;
    }
    //得到状态
    public int getAppStatus() {
        return appStatus;
    }
    //设置状态
    public void setAppStatus(int appStatus) {
        this.appStatus = appStatus;
    }
    
}

 

3.创建一个BaseActivity继承 AppCompatActivity,在onCreate方法中判断是否要重启

public class BaseActivity extends AppCompatActivity {
	@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //判断app状态
        if (AppStatusManager.getInstance().getAppStatus() == AppStatus.STATUS_RECYCLE){
            //被回收,跳转到启动页面
            Intent intent = new Intent(this, StartActivity.class);
            startActivity(intent);
            finish();
            return;
        }
    }
}

 

4.项目中的Activity页面,只需要继承BaseActivity就可以了

public class TestActivity extends BaseActivity {
	@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);
    }
}

 

5.最后就是启动页面了,在页面跳转前将app状态调为正常

    public class StartActivity extends AppCompatActivity {

   	private ImageView sp;
   	
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.startup);
        
        sp=(ImageView) findViewById(R.id.imageView);
      
        
        sp.postDelayed(new Runnable() {
            @Override
            public void run() {
                //页面跳转  
                Intent intent = new Intent(SplashActivity.this, MainActivity.class);
            	//app状态改为正常
            	AppStatusManager.getInstance().setAppStatus(AppStatus.STATUS_NORMAL);
            	startActivity(intent);
            	finish();
            }
        }, 2500);
    }
}

     这个时候有人可能不明白了,为什么只设置了app的正常状态,就能起到重启的效果?
这个时候我们再回头看一开始说的原因中,就会恍然大悟。在手机内存不足的时候,会回收全局变量,这个时候在AppStatus 中的 STATUS_RECYCLE =-1; //被回收(设置为默认值)
STATUS_NORMAL=1;    //正常
两个变量也会被回收,也就是说,在开始页面设置的app状态已经失效。再次恢复页面的时候这些全局变量都会重建,此时app的状态就变成被回收了,在恢复页面的时候判断不通过便会重新启动软件了。

 

参考:https://blog.csdn.net/Silence_Yong/article/details/82804808

           https://blog.csdn.net/xx326664162/article/details/79191853

你可能感兴趣的:(android)