对于应用的退出,我一直以来都有一个误区,我曾经简单地认为,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)。我感觉两种方法的区别更多的是设计上的倾向,无关优劣。