对于应用的退出,我一直以来都有一个误区,我曾经简单地认为,finish()是结束一个Activity的,System.exit(0)是结束整个Application的,直到有一天.....
---------------------我是华丽的分割线--------------------这是一个惊悚的故事------------------------------------------------------------------------------------------
曾经,有一个android应用是这样的:
主Activity的布局文件:
1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
2 xmlns:tools="http://schemas.android.com/tools"
3 android:layout_width="match_parent"
4 android:layout_height="match_parent"
5 android:paddingBottom="@dimen/activity_vertical_margin"
6 android:paddingLeft="@dimen/activity_horizontal_margin"
7 android:paddingRight="@dimen/activity_horizontal_margin"
8 android:paddingTop="@dimen/activity_vertical_margin"
9 tools:context=".MainActivity" >
10
11 <TextView
12 android:id="@+id/txt"
13 android:layout_width="match_parent"
14 android:layout_height="wrap_content"
15 android:layout_alignParentTop="true"
16 android:text="this is the first activity" />
17
18 <Button
19 android:id="@+id/btn"
20 android:layout_width="wrap_content"
21 android:layout_height="wrap_content"
22 android:layout_below="@+id/txt"
23 android:layout_centerHorizontal="true"
24 android:onClick="btnClick"
25 android:text="跳转" />
26
27 </RelativeLayout>
请不要关注那些不太规范的细节,这只是一个故事!
然后Activity(Launcher)是这个样子的:
1 public class MainActivity extends Activity {
2
3 @Override
4 protected void onCreate(Bundle savedInstanceState) {
5 super.onCreate(savedInstanceState);
6 setContentView(R.layout.activity_main);
7 }
8
9 public void btnClick(View v){
10 Intent intent=new Intent(MainActivity.this,SecondActivity.class);
11 startActivity(intent);
12 this.finish();//注意这个地方,接下来就是见证奇迹的时刻!!!
13 }
14
15 }
我们可以看到,我们还需要一个跳转的Activity,在这里:
public class SecondActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
LinearLayout layout=new LinearLayout(this);
TextView txt=new TextView(this);
txt.setText("this is the second activity");
Button btn=new Button(this);
btn.setText("退出");
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
System.exit(0);
}
});
layout.addView(txt);
layout.addView(btn);
setContentView(layout);
}
}
好了,一个最简单的跳转、关闭功能的android应用完成了。下面是效果图:
这似乎验证了System.exit(0)的有效性,但是,让我们回去看下Activity(Launcher)的代码,对,就是加注释那句,让我们去掉他会怎样呢?
接下来就是见证奇迹的时刻:
System.exit(0)失效了!!!!
------------------------------------------故事讲完了----------------------实在是惊悚-------------------------------------------------------------------------------------
为什么会出现这种效果呢,这是因为
finish():结束当前Activity,不会立即释放内存。遵循android内存管理机制。遵循activity的生命周期。
System.exit():结束当前组件如Activity,并立即释放当前Activity所占资源。不遵循activity的生命周期。
其实这里我是有疑问的,android是一个进程一个虚拟机,同一应用的activity默认是在同一个进程的,System.exit(0)(参数0代表正常退出)的作用是终止当前运行的虚拟机,为什么不能结束整个应用呢?如有了解的大神还望不吝指导。
说到这里,我们就需要考虑在没有将后台activity finish掉的情况下,怎样在前台activity退出整个应用?(在这里,我们不考虑释放内存、Service等其他组件的关闭以及可能需要在activity生命周期中处理的一系列操作)
现在流行的靠谱方法有两种:一种是使用单例模式创建一个自定义栈来管理activity,实现exit()方法遍历所有activity并finish()掉,但是我不喜欢并且没用过这种方法,所以有需要的可以自己在网上搜索,例子还是蛮多的。我在这里要介绍的是第二种方法,创建activity基类BaseActivity完成退出。
具体的实现是这样的:
先创建一个基类BaseActivity
1 public class BaseActivity extends Activity {
2 public Activity activity;
3 public ExitAllBroadCast exitAllBroadCast;
4
5 @Override
6 protected void onCreate(Bundle savedInstanceState) {
7 super.onCreate(savedInstanceState);
8 activity = BaseActivity.this;
9 exitAllBroadCast = new ExitAllBroadCast();
10
11 }
12
13 @Override
14 protected void onStart() {
15 IntentFilter filter = new IntentFilter();// 创建IntentFilter对象
16 filter.addAction("com.all.exit.broadcast");
17 registerReceiver(exitAllBroadCast, filter);// 注册Broadcast Receiver
18 super.onStart();
19 }
20 class ExitAllBroadCast extends BroadcastReceiver{
21
22 @Override
23 public void onReceive(Context context, Intent intent) {
24
25 activity.finish();
26 }
27
28 }
29 @Override
30 protected void onDestroy() {
31
32 super.onDestroy();
33 unregisterReceiver(exitAllBroadCast);
34 }
35 }
在基类中,我们注册了一个广播接收器,当接收到“com.all.exit.broadcast”广播时,就执行finish()。
现在,我们让所有的Activity都来继承这个BaseActivity,当我们想要退出的时候,发送广播就好了
1 Intent myIntent = new Intent();// 创建Intent对象
2 myIntent.setAction("com.all.exit.broadcast");
3 sendBroadcast(myIntent);// 发送广播
其实,这个方法的使用场景是我们希望能够直接在子界面中关闭应用,而在设计应用时,我更倾向于使用back键由子界面返回主界面并finish,然后在主界面使用back键主动完成主界面activity的生命周期并System.exit(0)。我感觉两种方法的区别更多的是设计上的倾向,无关优劣。