前言
最近由于项目的修改,项目由MainActivity按返回键一次退出修改为MainActivity中连续按两次返回键退出,顺便优化一下推出这里的代码。因此还是在网上搜索了一番,总结比较之后得出了有以下集中方式,优缺点都会提出来,有需要的老铁按需选择。
目录
常见的有5中方式:
- 容器式
- 便捷式
- 广播式
- SingleTask式
- 进程式
实现方法
1.容器式
容器式可能是我们最常见的方式之一了,主要通过创建一个全局的容器,把所有的Activity都保存下来,退出的时候循环遍历所有activity,然后finish()掉。
BaseActivity添加代码:
public abstract class BaseActivity extends AppCompatActivity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 添加Activity到堆栈
ActivityUtils.getInstance().addActivity(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
// 结束Activity&从栈中移除该Activity
ActivityUtils.getInstance().removeActivity(this);
}
}
创建一个全局工具类:
public class ActivityUtils{
private ActivityUtils() {
}
private static AtyContainer instance = new AtyContainer();
private static List<Activity> activitys = new ArrayList<Activity>();
public static ActivityUtils getInstance() {
return instance;
}
public void addActivity(Activity activity) {
activityStack.add(activity);
}
public void removeActivity(Activity activity) {
activityStack.remove(activity);
}
/**
* 结束所有Activity
*/
public void finishAllActivity() {
for (int i = 0, size = activityStack.size(); i < size; i++) {
if ( != activityStack.get(i)) {
activityStack.get(i).finish();
}
}
activityStack.clear();
}
}
这种方式是有一定的缺点的,我们的工具类ActivityUtils持有Activity的引用,当我们的应用发生异常,ActivityUtils持有的引用没有被销毁会导致部分内存问题,而且代码量多,不够优雅,诸多不便。
但是容器式这种方式还是有解决办法的,我们可以采用弱引用的方式,就不存在前面所说的问题了,习惯于容器式的可以采用弱引用这种方式的。
2.便捷式
在之前,先讲一下Activity的启动模式:SingleTask
我们知道Activity有四种加载模式,而singleTask就是其中的一种,使用这个模式之后,当startActivity时,它先会在当前栈中查询是否存在Activity的实例,如果存在,则将其至于栈顶,并将其之上的所有Activity移除栈。我们打开一个app,首先是一个splash页面,然后会finish掉splash页面。跳转到主页。然后会在主页进行N次的跳转,期间会产生数量不定的Activity,有的被销毁,有的驻留在栈中,但是栈底永远是我们的HomeActivity。这样就让问题变得简单很多了。我们只需两步操作即可优雅的实现app的退出。
有了这么一个启动模式,就好办了,我们将退出的出口放在MainActivity中所有事都解决了。
那么这种方法为什么叫便捷式呢?这种方式代码量很少而且很好理解、优雅,而且市面上很多APP都是基于此实现的。我们在MainActivity中实现如下代码:
private boolean isExit;
/**
* 双击返回键退出
*/
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (isExit) {
this.finish();
} else {
Toast.makeText(this, "再按一次退出", Toast.LENGTH_SHORT).show();
mIsExit = true;
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
isExit= false;
}
}, 2000);
}
return true;
}
return super.onKeyDown(keyCode, event);
}
不要着急,不要以为就完了,还有很重要的一步:将MainActivity设置为singleTask。
<activity android:name=".MainActivity"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
上面这种方法就是我个人认为最简便的方式了,这也符合有些要求按2次退出。
3.广播式
我相信很多的老铁是使用的广播式,毕竟很方便,先上代码,再说利弊。
public abstract class BaseActivity extends Activity {
private static final String ACTION = "action.exit";
private ExitReceiver exitReceiver = new ExitReceiver();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION);
registerReceiver(exitReceiver, filter);
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(exitReceiver);
}
class ExitReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
BaseActivity.this.finish();
}
}
}
最后再需要退出的地方,发送一个广播就可以了,注意Action和注册的相同就可以了。
但是个人觉得这种方式还是太耗性能,毕竟广播是进程间通信,我们一个退出APP功能不是特别的有必要。
4.SingleTask式
简单解释一下SingleTask这种启动模式的两个特点:
清除堆栈中处于当前Activity上方的Activity
堆栈中含有你要启动的Activity时,不会重新创建。
假设我们的MainActivity是使用的SingleTask的启动模式,假设我跳转到了其他的页面,然后使用startActivity(this,MainActivity.class)的方式再次启动MainActivity,这时MainActivity走到onNewIntent()方法,然后按照生命周期onRestart()——>onStart()——>onResume(),MainActivity不会重新创建。
既然有这么一个特点我们就可以分三步来退出APP:
第一步:MainActivity设置为SingleTask。
android:launchMode="singleTask"
第二步:重写MainActivity中的onNewIntent方法
private static final String TAG_EXIT = "exit";
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if (intent != ) {
boolean isExit = intent.getBooleanExtra(TAG_EXIT, false);
if (isExit) {
this.finish();
}
}
}
第三步:需要退出时在Intent中添加退出的tag
Intent intent = new Intent(this,MainActivity.class);
intent.putExtra(MainActivity.TAG_EXIT, true);
startActivity(intent);
虽然这种方式简单、便捷,但还有弊端:当我们需要退出的时候,假如是在其他的Activity中退出,这时MainActivity要走一段生命周期的方法,有点浪费。
5.进程式
1.android.os.Process.killProcess(android.os.Process.myPid());
2.System.exit(0);
3.ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
manager.killBackgroundProcesses(getPackageName());
这三种方式都能够达到杀死进程的效果,直接退出APP,但是这种太暴力了不推荐使用,而且使用体验不好。不知道是不是华为手机问题,我用华为P10 Plus使用这种方式退出的时候要白屏、闪屏一下,反正就是不建议使用这种方式。
总结
其实严格来说,还有一种方式就是抛异常让APP强制退出,因为感觉用的人不多就没有细说。
上面的几种方式中,最不推荐的就是最后第五种方式,暴力而且用户体验不好。大家在项目中看着需求、以及自己习惯的方式来选择就好,今天就到这里了。
推荐补脑的《Activity的四种启动模式》:https://blog.csdn.net/sharpeha/article/details/89348627
备注:程序圈LT