我们先来看看几种常见的退出方法(不优雅的方式)。
一、容器式
建立一个全局容器,把所有的activity存储起来,退出时循环遍历finish所有activity
import java.util.arraylist;
import java.util.list;
import android.app.activity;
import android.os.bundle;
public class baseactivity extends activity {
@override
protected void oncreate(bundle savedinstancestate) {
super.oncreate(savedinstancestate);
// 添加activity到堆栈
atycontainer.getinstance().addactivity(this);
}
@override
protected void ondestroy() {
super.ondestroy();
// 结束activity&从栈中移除该activity
atycontainer.getinstance().removeactivity(this);
}
}
class atycontainer {
private atycontainer() {
}
private static atycontainer instance = new atycontainer();
private static list activitystack = new arraylist();
public static atycontainer getinstance() {
return instance;
}
public void addactivity(activity aty) {
activitystack.add(aty);
}
public void removeactivity(activity aty) {
activitystack.remove(aty);
}
/**
* 结束所有activity
*/
public void finishallactivity() {
for (int i = 0, size = activitystack.size(); i < size; i++) {
if (null != activitystack.get(i)) {
activitystack.get(i).finish();
}
}
activitystack.clear();
}
}
这种方法比较简单, 但是可以看到activitystack持有这activity的强引用,也就是说当某个activity异常退出时,activitystack没有即使释放掉引用,就会导致内存问题,接下来我们看一种类似的方式,但是会稍微优雅一点点
二、广播式
通过在baseactivity中注册一个广播,当退出时发送一个广播,finish退出
public class baseactivity extends activity {
private static final string exitaction = "action.exit";
private exitreceiver exitreceiver = new exitreceiver();
@override
protected void oncreate(bundle savedinstancestate) {
super.oncreate(savedinstancestate);
intentfilter filter = new intentfilter();
filter.addaction(exitaction);
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();
}
}
}
三、进程式
通过直接杀死当前应用的进程来结束应用,简单粗暴,而且有(wu)效!
android.os.process.killprocess(android.os.process.mypid());
system.exit(0);
activitymanager manager = (activitymanager) getsystemservice(activity_service);
manager.killbackgroundprocesses(getpackagename());
这三种都能达到同样的效果,但是在模拟器上都会弹出 unfortunately , xxx has stopped 消息提示框,但确实能退出应用。部分真机直接失效,只能finish当前activity(比如我手上这台小米note,国产的几款rom fw层改动太多,使用这种方式需慎重) 。
四、 rs优雅式
什么是rs式呢?即receiver+singletask 。我们知道activity有四种加载模式,而singletask就是其中的一种,使用这个模式之后,当startactivity时,它先会在当前栈中查询是否存在activity的实例,如果存在,则将其至于栈顶,并将其之上的所有activity移除栈。我们打开一个app,首先是一个splash页面,然后会finish掉splash页面。跳转到主页。然后会在主页进行n次的跳转,期间会产生数量不定的activity,有的被销毁,有的驻留在栈中,但是栈底永远是我们的homeactivity。这样就让问题变得简单很多了。我们只需两步操作即可优雅的实现app的退出。
1、在homeactivity注册一个退出广播,和第二个广播式一样,但是这里只需要在homeactivity一个页面注册即可。
2、设置homeactivity的启动模式为singletask。
当我们需要退出的时候只需要startactivity(this,homeactivity,class), 再发送一个退出广播。上面代码首先会把栈中homeactivity之上的所有activity移除出栈,然后接到广播finish自己。一切ok ! 没有弹框,不用考虑机型rom适配。不会有内存问题,就是那么的优雅,简单!
五、singletask改版式
和一些小伙交流之后,很多小伙伴说注册广播略显麻烦,在楼下的小伙伴提出了一种更简单的方式,思路也很简单,
1、设置mainactivity的加载模式为singletask
2、重写mainactivity中的onnewintent方法
3、需要退出时在intent中添加退出的tag
由于很多小伙伴对需求比较热切,我们这里就直接以代码的形式为大家讲解这种方式
第一步设置mainactivity的加载模式为singletask
android:launchmode="singletask"
1
第二步重写onnewintent()方法
private static final string tag_exit = "exit";
@override
protected void onnewintent(intent intent) {
super.onnewintent(intent);
if (intent != null) {
boolean isexit = intent.getbooleanextra(tag_exit, false);
if (isexit) {
this.finish();
}
}
}
第三步 退出
intent intent = new intent(this,mainactivity.class);
intent.putextra(mainactivity.tag_exit, true);
startactivity(intent);
六、懒人式?
这种方式更加简单,只需要如下两步操作?
1、将mainactivity设置为singletask?
2、将退出出口放置在mainactivity?
我们可以看到很多应用都是双击两次home键退出应用,就是基于这样的方式来实现的,这里在贴一下如何处理连续两次点击退出的源码
private boolean misexit;
@override
/**
* 双击返回键退出
*/
public boolean onkeydown(int keycode, keyevent event) {
if (keycode == keyevent.keycode_back) {
if (misexit) {
this.finish();
} else {
toast.maketext(this, "再按一次退出", toast.length_short).show();
misexit = true;
new handler().postdelayed(new runnable() {
@override
public void run() {
misexit = false;
}
}, 2000);
}
return true;
}
return super.onkeydown(keycode, event);
}
如对本文有疑问, 点击进行留言回复!!
Codeforces C. A Cookie for You (模拟 / 分类 / 贪心) (Round #654 Div.2)
DialogFragment弹窗(带黑色透明背景和不带黑色透明背景)
android 常用布局文件(LinearLayout,RelativeLayout,FrameLayout,ConstraintLayout,TableLayout)
网友评论