做Android开发的小朋友一定会遇到程序退到后台,遇到内存被回收,导致数据为空,这时候启动APP就会出现空指针问题。
那么,我们该怎么解决这个问题呢?其实很简单,当内存被回收后,我们可以直接重启APP,重新走一遍APP启动的流程,这样数据就会重新加载一遍,避免了数据为空的问题。
首先,我们先定义一个AppStatusManager
管理生命周期类
/**
* APP状态跟踪器常量码
*/
public class AppStatusConstant {
public static final int STATUS_FORCE_KILLED = -1; //应用放在后台被强杀了
public static final int STATUS_KICK_OUT = 1;//TOKEN失效或者被踢下线
public static final int STATUS_NORMAL = 2; //APP正常态
public static final int STATUS_LOGOUT = 3;//用户注销登录
public static final int STATUS_OFFLINE = 4;//未登录状态
public static final int STATUS_ONLINE = 5;//登录状态
//intent到MainActivity 区分跳转目的
public static final String KEY_HOME_ACTION = "key_home_action";//返回到主页面
public static final int ACTION_BACK_TO_HOME = 11; //默认值
public static final int ACTION_RESTART_APP = 12;//重启APP
public static final int ACTION_KICK_OUT = 13;//被踢出
public static final int ACTION_LOGOUT = 14;//退出登录
}
public class AppStatusManager implements Application.ActivityLifecycleCallbacks {
public int mAppStatus = AppStatusConstant.STATUS_FORCE_KILLED;
public static AppStatusManager mAppStatusManager;
private Application application;
private boolean isForground;//是否前台
private int activeCount;//Activity运行个数
private AppStatusManager(Application application) {
this.application = application;
application.registerActivityLifecycleCallbacks(this);
}
public static void init(Application application) {
if (mAppStatusManager == null) {
mAppStatusManager = new AppStatusManager(application);
}
}
public static AppStatusManager getInstance() {
return mAppStatusManager;
}
/**
* 获取APP状态
*/
public int getAppStatus() {
return mAppStatus;
}
/**
* 设置APP状态
*/
public void setAppStatus(int appStatus) {
this.mAppStatus = appStatus;
}
/**
* 是否前台显示
*/
public boolean isForground() {
return isForground;
}
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
@Override
public void onActivityStarted(Activity activity) {
activeCount++;
}
@Override
public void onActivityResumed(Activity activity) {
isForground = true;
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
activeCount--;
if (activeCount == 0) {
isForground = false;
}
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
}
}
public class BaseApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
AppStatusManager.init(this);
}
}
然后定义个TrackerActivity
基类,监听内存回收问题
public abstract class TrackerActivity extends AppCompatActivity {
private String TAG = "TAG";
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
switch (AppStatusManager.getInstance().getAppStatus()) {
case AppStatusConstant.STATUS_FORCE_KILLED:
Log.e(TAG, "STATUS_FORCE_KILLED");
/*处理APP被强杀*/
protectApp();
break;
case AppStatusConstant.STATUS_KICK_OUT:
/*处理APP被退出登录*/
Log.e(TAG, "STATUS_KICK_OUT");
break;
case AppStatusConstant.STATUS_NORMAL:
/*APP正常状态*/
Log.e(TAG, "STATUS_NORMAL");
setUpContentView();
setUpData();
break;
}
}
/**
* 设置布局
*/
protected abstract void setUpContentView();
/**
* 设置数据
*/
protected abstract void setUpData();
/**
* 处理APP被强杀
*/
protected void protectApp() {
/*跳转主界面处理*/
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra(AppStatusConstant.KEY_HOME_ACTION, AppStatusConstant.ACTION_RESTART_APP);
startActivity(intent);
}
}
接下来,我们只用在实现SplashActivity
MainActivity
SecondActivity
,就行了
SplashActivity
public class SplashActivity extends TrackerActivity {
private MyHandler mHandler = new MyHandler(this);
@Override
protected void onCreate(Bundle savedInstanceState) {
//设置默认状态
AppStatusManager.getInstance().setAppStatus(AppStatusConstant.STATUS_NORMAL);
super.onCreate(savedInstanceState);
}
@Override
protected void setUpContentView() {
setContentView(R.layout.activity_splash);
}
@Override
protected void setUpData() {
if (mHandler != null) {
mHandler.sendEmptyMessageDelayed(0, 2000);
}
}
private static class MyHandler extends Handler {
private WeakReference<Context> reference;
public MyHandler(Context context) {
reference = new WeakReference<>(context);
}
@Override
public void handleMessage(Message msg) {
SplashActivity activity = (SplashActivity) reference.get();
if (activity != null) {
activity.startActivity(new Intent(activity, MainActivity.class));
activity.finish();
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mHandler != null) {
mHandler.removeCallbacksAndMessages(null);
mHandler = null;
}
}
}
MainActivity
public class MainActivity extends TrackerActivity {
@Override
protected void setUpContentView() {
setContentView(R.layout.activity_main);
}
@Override
protected void setUpData() {
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
int action = intent.getIntExtra(AppStatusConstant.KEY_HOME_ACTION, AppStatusConstant.ACTION_BACK_TO_HOME);
switch (action) {
case AppStatusConstant.ACTION_RESTART_APP:
protectApp();
break;
case AppStatusConstant.ACTION_BACK_TO_HOME:
break;
default:
break;
}
}
@Override
protected void protectApp() {
/*跳转引导页,重启APP*/
startActivity(new Intent(this, SplashActivity.class));
finish();
}
public void toSecondActivity(View view) {
startActivity(new Intent(this, SecondActivity.class));
}
}
SecondActivity
public class SecondActivity extends TrackerActivity {
@Override
protected void setUpContentView() {
setContentView(R.layout.activity_second);
}
@Override
protected void setUpData() {
}
public void toThirdActivity(View view) {
startActivity(new Intent(this, ThirdActivity.class));
}
大功告成!!! 让我们看看具体显示流程吧
流程: SplashActivity -> MainActivity -> SecondActivity -> ThirdActivity -> APP被强杀,内存被回收,APP就会重启,重走流程 -> SplashActivity -> MainActivity