Android 开发知识点

1.退出:

完全退出:

 一、记录打开过的activity,然后在退出的时候   遍历数组 关闭

[java]  view plain
  1. <span style="font-family:SimSun;font-size:14px;">public class ExitUtil {   
  2.     //定义一个activity列表  
  3.     private List<Activity> mList = new ArrayList<Activity>();   
  4.       
  5.    //顶一一个类的实例  
  6.     private static ExitUtil instance;   
  7.       
  8.     //私有构造方法 不允许创建类的实例  
  9.     private ExitUtil() {     
  10.     }   
  11.   
  12.     /** 
  13.      * 单例模式 
  14.      * @return 
  15.      */  
  16.     public  static ExitUtilgetInstance() {   
  17.         if (null == instance) {   
  18.             instance = new ExitUtil();   
  19.         }   
  20.         return instance;   
  21.     }   
  22.        
  23.     /** 
  24.      * 如果activity已经 destory了 就移除 
  25.      * @param activity 
  26.      */  
  27.     public  void remove(Activity activity){     
  28.           
  29.         mList.remove(activity);     
  30.              
  31.     }     
  32.   
  33.     /** 
  34.      * 添加ativity 
  35.      * @param activity 
  36.      */  
  37.     public void addActivity(Activity activity) {   
  38.         mList.add(activity);   
  39.     }   
  40.     /** 
  41.      * 遍历  结束activity  并且退出 
  42.      */  
  43.         public void exit() {   
  44.         try {   
  45.             for (Activity activity : mList) {   
  46.                 if (activity != null)   
  47.                     activity.finish();   
  48.             }   
  49.               
  50.         } catch (Exception e) {   
  51.             e.printStackTrace();   
  52.         } finally {   
  53.             android.os.Process.killProcess(android.os.Process.myPid());     
  54.             System.exit(0);   
  55.         }   
  56.     }   
  57.   
  58.   
  59.   
  60. }</span>  

一般推荐在写程序的时候,自己顶一个commonactivity  继承activity  作为自己activity的父类 

这样比较方便  你可以在自己的commonactivity中调用一下退出类的添加和移除方法 比较方便

[java]  view plain
  1. <span style="font-family:SimSun;font-size:14px;">   @Override  
  2.     protected void onCreate(Bundle savedInstanceState) {  
  3.         // TODO Auto-generated method stub  
  4.         ExitUtil.getInstance().addActivity(this);  
  5.         super.onCreate(savedInstanceState);  
  6.               
  7.     }</span>  


 

[java]  view plain
  1. <span style="font-family:SimSun;font-size:14px;">   @Override  
  2.     protected void onDestroy() {  
  3.         // TODO Auto-generated method stub  
  4.         super.onDestroy();  
  5.         ExitUtil.getInstance().remove(this);  
  6.             }  
  7. </span>  


这样  在退出的界面中  调用下exit方法就可以了

[java]  view plain
  1. <span style="font-family:SimSun;font-size:14px;">   @Override  
  2.     public boolean onKeyDown(int keyCode, KeyEvent event) {  
  3.         // 按下键盘上返回按钮  
  4.         if (keyCode == KeyEvent.KEYCODE_BACK) {  
  5.             new AlertDialog.Builder(this)  
  6.                     .setTitle("提示")  
  7.                     .setMessage("确认退出")  
  8.                     .setNegativeButton("取消",  
  9.                             new DialogInterface.OnClickListener() {  
  10.                                 public void onClick(DialogInterface dialog,  
  11.                                         int which) {  
  12.                                 }  
  13.                             })  
  14.                     .setPositiveButton("确定",  
  15.                             new DialogInterface.OnClickListener() {  
  16.                                 public void onClick(DialogInterface dialog,  
  17.                                         int whichButton) {  
  18.                                 //  closed();  
  19.                                     ExitUtil.getInstance().exit();  
  20.                                 }  
  21.                             }).show();  
  22.   
  23.             return true;  
  24.         } else {  
  25.             return super.onKeyDown(keyCode, event);  
  26.         }  
  27.     }  
  28.     </span>  


这样  就可以成功的退出

二、广泛采用的  采用广播退出的方法

也是在自己定义的commoactivity中   注册个广播 如果接到广播 结束activity

[java]  view plain
  1. <span style="font-family:SimSun;font-size:14px;">   public BroadcastReceiver    broadcastReceiver = new  BroadcastReceiver() {  
  2.           
  3.         @Override  
  4.         public void onReceive(Context context, Intent intent) {  
  5.             // TODO Auto-generated method stub  
  6.             finish();  
  7.         }  
  8.     };</span>  

这个需要在onresume中注册广播  这里的GlobalVarable.EXIT_ACTION是自己定义的一个action

[java]  view plain
  1. <span style="font-family:SimSun;font-size:14px;">@Override  
  2.     protected void onResume() {  
  3.         // TODO Auto-generated method stub  
  4.         super.onResume();  
  5.     IntentFilter filter = new IntentFilter();  
  6.       filter.addAction(GlobalVarable.EXIT_ACTION);</span>  
[java]  view plain
  1. <span style="font-family:SimSun;font-size:14px;">   this.registerReceiver(this.broadcastReceiver, filter);</span>  
}


需要注意的是  要在ondestory中解除注册 否则会报异常

[java]  view plain
  1. <span style="font-family:SimSun;font-size:14px;">   @Override  
  2.     protected void onDestroy() {  
  3.         // TODO Auto-generated method stub  
  4.         super.onDestroy();  
  5.         this.unregisterReceiver(broadcastReceiver);  
  6.     }</span>  


 

然后 在退出的时候调用close方法发送广播
[java]  view plain
  1. <span style="font-family:SimSun;font-size:14px;">   private void closed(){  
  2.         Intent intent = new Intent();  
  3.         intent.setAction(GlobalVarable.EXIT_ACTION); // 退出动作  
  4.         this.sendBroadcast(intent);// 发送广播  
  5.         super.finish();  
  6.         //退出后台线程,以及销毁静态变量  
  7.         System.exit(0);  
  8.     }  
  9.         </span>  

三、定义一个 MyApplication extends Application 在MyApplication中定义一个全局变量

private boolean isExit = false;
 public boolean isExit() {
  return isExit;
 }
 public void setExit(boolean isExit) {
  this.isExit = isExit;

并且在commonactivity中的onsatrt方法中判断  如果为true就关闭当前activity

[java]  view plain
  1. <span style="font-family:SimSun;font-size:14px;">   @Override  
  2.     protected void onStart() {  
  3.         // TODO Auto-generated method stub  
  4.          MyApplication application = (MyApplication) this.getApplication();  
  5.          if(application.isExit()==true){  
  6.              this.finish();  
  7.          }  
  8.         super.onStart();  
  9.     }  
  10.     </span>  

 

如果需要退出  则在当前界面中将isExit设为True并且结束当前activity  就可以退出所以activity

值得注意的是 如果想要MyApplication起作用 需要在配置文件中的Application设置成自己的MyApplication

因为系统默认的是Application

----------------------------------------------------------------------------

1. finish()方法

该方法可以结束当前 Activity,但是如果你的App有很多 Activity 的话,使用该方法显得有点捉襟见肘了。

另外,还有一个方法finishActivity (int requestCode) ,关于这个方法,先看看sdk的api说明吧!

  1. public void finishActivity (int requestCode) 
  2. Since: API Level 1 
  3. Force finish another activity that you had previously started with startActivityForResult(Intent, int). 
  4. Parameters requestCode  The request code of the activity that you had given to startActivityForResult(). If there are multiple activities started with this request code, they will all be finished. 

也许你会这样理解 ,Activity1 通过方法 startActivityForResult (Intent, int) 启动 Activity2,然后在 Activity2 中通过方法finishActivity (int requestCode)来结束 Activity1,但是很不幸运,不是这样的。不信你可以Demo一把!

上面文档说得很明白,该方法强制关闭通过方法 startActivityForResult (Intent, int) 启动的 Activity,也就是说在 Activity1 中的(重写)方法onActivityResult(int requestCode, int resultCode, Intent data) 来接收 Activity2 返回的结果,必须在 Activity1 中调用finishActivity (int requestCode)来结束 Activity2。(一般在onActivityResult 方法调用该方法结束 Activity2)。

  1. Force finish another activity that you had previously started with startActivityForResult(Intent, int). 
  2. Parameters 

还有,下面两个方法,可以参阅文档以及源码研究一下。

  1. finishActivityFromChild(Activity child, int requestCode) 
  2. finishFromChild(Activity child) 

2. killProcess

通过调用 android.os.Process 的相关方法,结束 App,示例如下:

  1. btn_exit.setOnClickListener(new Button.OnClickListener() { 
  2.     @Override 
  3.     public void onClick(View v) { 
  4.         android.os.Process.killProcess(android.os.Process.myPid()); 
  5.     } 
  6.       }); 

3. exit

我们知道,Java 的 exit(int code) 方法可以退出程序,通过查看该方法源码,知道它实际上是调用下面的方法:

  1. Runtime.getRuntime().exit(code); 

示例代码,如下所示:

  1. btn_exit.setOnClickListener(new Button.OnClickListener() { 
  2.             @Override 
  3.             public void onClick(View v) { 
  4.                 System.exit(0);//正常退出App 
  5.             } 
  6.         }); 

接下来,我们研究一下这个方法。java.lang.System这个类的该方法jdk说明:

  1. exit 
  2.  
  3. public static void exit(int status) 
  4. 终止当前正在运行的 Java 虚拟机。参数用作状态码;根据惯例,非 0 的状态码表示异常终止。 
  5. 该方法调用 Runtime 类中的 exit 方法。该方法永远不会正常返回。 
  6.  
  7. 调用 System.exit(n) 实际上等效于调用: 
  8.  
  9. Runtime.getRuntime().exit(n) 
  10.   
  11. 参数: 
  12. status - 退出状态。 
  13. 抛出: 
  14. SecurityException - 如果安全管理器存在并且其 checkExit 方法不允许以指定状态退出。 
  15. 另请参见: 
  16. Runtime.exit(int) 

也就是说,参数为非0值的话是异常退出程序。参数为0的话,就是正常退出。

看RunTime这个类的该方法源码:

  1. public void exit(int status) { 
  2.         SecurityManager security = System.getSecurityManager(); 
  3.     if (security != null) { 
  4.         security.checkExit(status); 
  5.     } 
  6.     Shutdown.exit(status); 

其api说明:

  1. exit 
  2.  
  3. public void exit(int status) 
  4. 通过启动虚拟机的关闭序列,终止当前正在运行的 Java 虚拟机。此方法从不正常返回。可以将变量作为一个状态码;根据惯例,非零的状态码表示非正常终止。 
  5. 虚拟机的关闭序列包含两个阶段。在第一个阶段中,会以某种未指定的顺序启动所有已注册的关闭钩子 (hook)(如果有的话),并且允许它们同时运行直至结束。在第二个阶段中,如果已启用退出终结,则运行所有未调用的终结方法。一旦完成这个阶段,虚拟机就会暂停。 
  6.  
  7. 如果在虚拟机已开始其关闭序列后才调用此方法,那么若正在运行关闭钩子,则将无限期地阻断此方法。如果已经运行完关闭钩子,并且已启用退出终结 (on-exit finalization),那么此方法将利用给定的状态码(如果状态码是非零值)暂停虚拟机;否则将无限期地阻断虚拟机。 
  8.  
  9. System.exit 方法是调用此方法的一种传统而便捷的方式。 
  10.  
  11. 参数: 
  12. status - 终止状态。按照惯例,非零的状态码表明非正常终止。 
  13. 抛出: 
  14. SecurityException - 如果安全管理器存在,并且其 checkExit 方法不允许存在指定的状态 
  15. 另请参见: 
  16. SecurityException, SecurityManager.checkExit(int), addShutdownHook(java.lang.Thread), removeShutdownHook(java.lang.Thread), runFinalizersOnExit(boolean), halt(int) 

该方法又是调用Shutdown这个类的exit()方法。

  1. static void exit(int status) { 
  2.     boolean runMoreFinalizers = false
  3.     synchronized (lock) { 
  4.         if (status != 0) runFinalizersOnExit = false
  5.         switch (state) { 
  6.         case RUNNING:   /* Initiate shutdown */ 
  7.         state = HOOKS; 
  8.         break
  9.         case HOOKS:     /* Stall and halt */ 
  10.         break
  11.         case FINALIZERS: 
  12.         if (status != 0) { 
  13.             /* Halt immediately on nonzero status */ 
  14.             halt(status); 
  15.         } else { 
  16.             /* Compatibility with old behavior:
  17.              * Run more finalizers and then halt
  18.              */ 
  19.             runMoreFinalizers = runFinalizersOnExit; 
  20.         } 
  21.         break
  22.         } 
  23.     } 
  24.     if (runMoreFinalizers) { 
  25.         runAllFinalizers(); 
  26.         halt(status); 
  27.     } 
  28.     synchronized (Shutdown.class) { 
  29.         /* Synchronize on the class object, causing any other thread
  30.              * that attempts to initiate shutdown to stall indefinitely
  31.          */ 
  32.         sequence(); 
  33.         halt(status); 
  34.     } 
  35.     } 

其中,runAllFinalizers()是一个本地方法:

  1. JNIEXPORT void JNICALL 
  2. Java_java_lang_Shutdown_runAllFinalizers(JNIEnv *env, jclass ignored) 
  3.     jclass cl; 
  4.     jmethodID mid; 
  5.  
  6.     if ((cl = (*env)->FindClass(env, "java/lang/ref/Finalizer")) 
  7.     && (mid = (*env)->GetStaticMethodID(env, cl, 
  8.                         "runAllFinalizers""()V"))) { 
  9.     (*env)->CallStaticVoidMethod(env, cl, mid); 
  10.     } 

System.exit()的参数是把退出原因返回给系统, 一般来说可以是任何的整数 。

0表示正常退出,1表示非正常 。

最后说一下finish()与exit方法的区别:

finish()是Activity的类方法,仅仅针对Activity,当调用finish()时,只是将活动推向后台,并没有立即释放内存,活动的资源并没有被清理;当调用System.exit(0)时,退出当前Activity并释放资源(内存),但是该方法不可以结束整个App如有多个Activty或者有其他组件service等不会结束。

其实android的机制决定了用户无法完全退出应用,当你的application最长时间没有被用过的时候,android自身会决定将application关闭了。


4. restartPackage方法

  1. ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);     
  2. manager.restartPackage(getPackageName()); 

首先需要创建ActivityManager对象,然后调用restartPackage()方法(如果有兴趣的话,可以看源码)。

注意:getPackageName获得当前应用包名称,如mark.zhang

使用这种方式来退出App,需要权限:

  1. <uses-permission android:name="android.permission.RESTART_PACKAGES" /> 

更加详细的说明,如下:

  1. void android.app.ActivityManager.restartPackage(String packageName) 
  2.  
  3. Have the system perform a force stop of everything associated with the given application package. All processes that share its uid will be killed, all services it has running stopped, all activities removed, etc. In addition, a Intent.ACTION_PACKAGE_RESTARTED broadcast will be sent, so that any of its registered alarms can be stopped, notifications removed, etc. 
  4.  
  5. You must hold the permission android.Manifest.permission.RESTART_PACKAGES to be able to call this method. 
  6.  
  7. Parameters: 
  8.     packageName The name of the package to be stopped. 

可以看出,相同的UID的进程会被kill,还会停止相关的服务以及移除所有的Activity,并且会发送一个广播。


注意一个问题:在android2.2之后,该方法不可以将应用程序结束,需要使用ActivityManager类的下面这个方法:

  1. public void killBackgroundProcesses (String packageName) 

api 文档说的很清楚:

  1. public void restartPackage (String packageName) 
  2.  
  3. Since: API Level 3 
  4. This method is deprecated. 
  5. This is now just a wrapper for killBackgroundProcesses(String); the previous behavior here is no longer available to applications because it allows them to break other applications by removing their alarms, stopping their services, etc. 

另外,需要使用权限:

  1. <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>  

但是不管你怎么样折腾,还是无法退出App,呜呼哀哉!这里给出一个方法:

  1. int currentVersion = android.os.Build.VERSION.SDK_INT; 
  2.             if (currentVersion > android.os.Build.VERSION_CODES.ECLAIR_MR1) { 
  3.                 Intent startMain = new Intent(Intent.ACTION_MAIN); 
  4.                 startMain.addCategory(Intent.CATEGORY_HOME); 
  5.                 startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
  6.                 startActivity(startMain); 
  7.                 System.exit(0); 
  8.             } else {// android2.1 
  9.                 ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE); 
  10.                 am.restartPackage(getPackageName()); 
  11.             } 


关于android.os.Build.VERSION.SDK_INT,可以参考 http://blog.csdn.net/androidbluetooth/article/details/6778422


5. 小结


finish():结束当前Activity,不会立即释放内存。遵循android内存管理机制。


exit():结束当前组件如Activity,并立即释放当前Activity所占资源。


killProcess():结束当前组件如Activity,并立即释放当前Activity所占资源。


restartPackage():结束整个App,包括service等其它Activity组件。


特别注意:除了finish()方法可以调用Activity的生命周期方法如onStop()、onDestroy(),其余三种退出App均不会调用Activity的生命周期方法。除非,在调用这几个方法之前或者之后主动调用Activity的生命周期方法。如:

  1. System.exit(int); 
  2. onDestroy(); 


 第六种方法:使用广播机制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public  abstract  class  EnterActivity extends  BaseActivity { 
... 
     // 写一个广播的内部类,当收到动作时,结束activity 
     private  BroadcastReceiver broadcastReceiver = new  BroadcastReceiver() { 
         @Override 
         public  void  onReceive(Context context, Intent intent) { 
             close(); 
             unregisterReceiver( this ); // 这句话必须要写要不会报错,不写虽然能关闭,会报一堆错 
        
     }; 
   
     @Override 
     public  void  onResume() { 
         super .onResume(); 
   
         // 在当前的activity中注册广播 
         IntentFilter filter = new  IntentFilter(); 
         filter.addAction(Attribute.PAGENAME); 
         registerReceiver( this .broadcastReceiver, filter); // 注册 
    
   
     /**
      * 关闭
      */ 
     public  void  close() { 
         Intent intent = new  Intent(); 
         intent.setAction(Attribute.PAGENAME); // 说明动作 
         sendBroadcast(intent); // 该函数用于发送广播 
         finish(); 
    
... 
}

    请注意,这段代码中缺少了注销代码,(unregisterReceiver)这个是必须要加的。


2.按HOME键后回到最后一次Activity:

   android:alwaysRetainTaskState 这个属性用来标记应用的task是否保持原来的状态,“true”表示总是保持,“false”表示不能够保证,默认为“false”。此属性只对task的根Activity起作用,其他的Activity都会被忽略。 默认情况下,如果一个应用在后台呆的太久例如30分钟,用户从主选单再次选择该应用时,系统就会对该应用的task进行清理,除了根Activity,其他Activity都会被清除出栈,但是如果在根Activity中设置了此属性之后,用户再次启动应用时,仍然可以看到上一次操作的界面。 这个属性对于一些应用非常有用,例如Browser应用程序,有很多状态,比如打开很多的tab,用户不想丢失这些状态,使用这个属性就极为恰当。

      注:android:launchMode="singleTask"在时不起作用

      扩展:1.android:allowTaskReparenting 这个属性用来标记一个Activity实例在当前应用退居后台后,是否能从启动它的那个task移动到有共同affinity的task,“true”表示可以移动,“false”表示它必须呆在当前应用的task中,默认值为false。如果一个这个Activity的元素没有设定此属性,设定在上的此属性会对此Activity起作用。例如在一个应用中要查看一个web页面,在启动系统浏览器Activity后,这个Activity实例和当前应用处于同一个task,当我们的应用退居后台之后用户再次从主选单中启动应用,此时这个Activity实例将会重新宿主到Browser应用的task内,在我们的应用中将不会再看到这个Activity实例,而如果此时启动Browser应用,就会发现,第一个界面就是我们刚才打开的web页面,证明了这个Activity实例确实是宿主到了Browser应用的task内。 

            2.android:clearTaskOnLaunch 这个属性用来标记是否从task清除除根Activity之外的所有的Activity,“true”表示清除,“false”表示不清除,默认为“false”。同样,这个属性也只对根Activity起作用,其他的Activity都会被忽略。 如果设置了这个属性为“true”,每次用户重新启动这个应用时,都只会看到根Activity,task中的其他Activity都会被清除出栈。如果我们的应用中引用到了其他应用的Activity,这些Activity设置了allowTaskReparenting属性为“true”,则它们会被重新宿主到有共同affinity的task中。 
            3.android:finishOnTaskLaunch 这个属性和android:allowReparenting属性相似,不同之处在于allowReparenting属性是重新宿主到有共同affinity的task中,而finishOnTaskLaunch属性是销毁实例。如果这个属性和android:allowReparenting都设定为“true”,则这个属性好些。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值