zoukankan      html  css  js  c++  java
  • Android知识整理(4) 关于Android应用的退出

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

  • 相关阅读:
    数据库设计主键定义思考
    dotnet(C#)的面试题,大家共享一下
    一些有创意的SQL语句
    asp.net(c#) 服务器探针
    存储过程共有三种返回值
    如何删除表中的重复记录?等等常用SQL语句的积累
    一般存储过程示例
    关于utf8,unicode字符集
    在Asp.net里利用DIV层元素弹出窗体
    数据库主键设计思考
  • 原文地址:https://www.cnblogs.com/lihualuo/p/3671000.html
Copyright © 2011-2022 走看看