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

posted on 2014-04-17 16:05  二十年梨花  阅读(917)  评论(1编辑  收藏  举报