android——徹底關閉——應用程式

來源:互聯網
上載者:User

標籤:

最近學習做android的遊戲開發時候,發現一個關於android退出時不能徹底關閉的問題,比如:一個程式裡new 出了N多個Thread,這樣在退出程式的可能不能完全關閉,最後發現,只用finish()方法,有時候不能徹底退出,個人感覺還是要在適當的地方加上:System.exit(0);

1. finish()方法

該方法可以結束當前 Activity,但是如果你的App有很多 Activity 的話,使用該方法顯得有點捉襟見肘了。

另外,還有一個方法finishActivity (int requestCode) ,關於這個方法,先看看sdk的api說明吧!

public void finishActivity (int requestCode)  Since: API Level 1  Force finish another activity that you had previously started with startActivityForResult(Intent, int).  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)。

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

還有,下面兩個方法,可以參閱文檔以及源碼研究一下。

finishActivityFromChild(Activity child, int requestCode)  finishFromChild(Activity child)  

2. killProcess

通過調用 android.os.Process 的相關方法,結束 App,樣本如下:

btn_exit.setOnClickListener(new Button.OnClickListener() {      @Override      public void onClick(View v) {          android.os.Process.killProcess(android.os.Process.myPid());      }  });  

3. exit

我們知道,Java 的 exit(int code) 方法可以退出程式,通過查看該方法源碼,知道它實際上是調用下面的方法:

Runtime.getRuntime().exit(code);  

範例程式碼,如下所示:

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

接下來,我們研究一下這個方法。java.lang.System這個類的該方法jdk說明:

exit    public static void exit(int status)  終止當前正在啟動並執行 JAVA 虛擬機器。參數用作狀態代碼;根據慣例,非 0 的狀態代碼表示異常終止。  該方法調用 Runtime 類中的 exit 方法。該方法永遠不會正常返回。    調用 System.exit(n) 實際上等效於調用:     Runtime.getRuntime().exit(n)     參數:  status - 退出狀態。  拋出:  SecurityException - 如果安全管理器存在並且其 checkExit 方法不允許以指定狀態退出。  另請參見:  Runtime.exit(int)  

也就是說,參數為非0值的話是異常退出程式。參數為0的話,就是正常退出。

 看RunTime這個類的該方法源碼:

public void exit(int status) {          SecurityManager security = System.getSecurityManager();      if (security != null) {          security.checkExit(status);      }      Shutdown.exit(status);  }  

其api說明:

public void exit(int status)  通過啟動虛擬機器的關閉序列,終止當前正在啟動並執行 JAVA 虛擬機器。此方法從不正常返回。可以將變數作為一個狀態代碼;根據慣例,非零的狀態代碼表示非正常終止。  虛擬機器的關閉序列包含兩個階段。在第一個階段中,會以某種未指定的順序啟動所有登入的關閉鉤子 (hook)(如果有的話),並且允許它們同時運行直至結束。在第二個階段中,如果已啟用退出終結,則運行所有未調用的終結方法。一旦完成這個階段,虛擬機器就會暫停。    如果在虛擬機器已開始其關閉序列後才調用此方法,那麼若正在運行關閉鉤子,則將無限期地阻斷此方法。如果已經運行完關閉鉤子,並且已啟用退出終結 (on-exit finalization),那麼此方法將利用給定的狀態代碼(如果狀態代碼是非零值)暫停虛擬機器;否則將無限期地阻斷虛擬機器。    System.exit 方法是調用此方法的一種傳統而便捷的方式。    參數:  status - 終止狀態。按照慣例,非零的狀態代碼表明非正常終止。  拋出:  SecurityException - 如果安全管理器存在,並且其 checkExit 方法不允許存在指定的狀態  另請參見:  SecurityException, SecurityManager.checkExit(int), addShutdownHook(java.lang.Thread), removeShutdownHook(java.lang.Thread), runFinalizersOnExit(boolean), halt(int)  

該方法又是調用Shutdown這個類的exit()方法。

static void exit(int status) {      boolean runMoreFinalizers = false;      synchronized (lock) {          if (status != 0) runFinalizersOnExit = false;          switch (state) {          case RUNNING:   /* Initiate shutdown */          state = HOOKS;          break;          case HOOKS:     /* Stall and halt */          break;          case FINALIZERS:          if (status != 0) {              /* Halt immediately on nonzero status */              halt(status);          } else {              /* Compatibility with old behavior:              * Run more finalizers and then halt              */              runMoreFinalizers = runFinalizersOnExit;          }          break;          }      }      if (runMoreFinalizers) {          runAllFinalizers();          halt(status);      }      synchronized (Shutdown.class) {          /* Synchronize on the class object, causing any other thread              * that attempts to initiate shutdown to stall indefinitely          */          sequence();          halt(status);      }      }  

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

JNIEXPORT void JNICALL  Java_java_lang_Shutdown_runAllFinalizers(JNIEnv *env, jclass ignored)  {      jclass cl;      jmethodID mid;        if ((cl = (*env)->FindClass(env, "java/lang/ref/Finalizer"))      && (mid = (*env)->GetStaticMethodID(env, cl,                          "runAllFinalizers", "()V"))) {      (*env)->CallStaticVoidMethod(env, cl, mid);      }  }  

System.exit()的參數是把退出原因返回給系統, 一般來說可以是任何的整數 。
0表示正常退出,1表示非正常 。

最後說一下finish()與exit方法的區別:

finish()是Activity的類方法,僅僅針對Activity,當調用finish()時,只是將活動推向後台,並沒有立即釋放記憶體,活動的資源並沒有被清理;當調用System.exit(0)時,退出當前Activity並釋放資源(記憶體),但是該方法不可以結束整個App如有多個Activty或者有其他組件service等不會結束。

其實android的機制決定了使用者無法完全退出應用,當你的application最長時間沒有被用過的時候,android自身會決定將application關閉了。

 4. restartPackage方法

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

首先需要建立ActivityManager對象,然後調用restartPackage()方法(如果有興趣的話,可以看源碼)。

注意:getPackageName獲得當前應用程式套件名稱,如mark.zhang

使用這種方式來退出App,需要許可權:

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

更加詳細的說明,如下:

void android.app.ActivityManager.restartPackage(String packageName)    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.    You must hold the permission android.Manifest.permission.RESTART_PACKAGES to be able to call this method.    Parameters:      packageName The name of the package to be stopped.  

可以看出,相同的UID的進程會被kill,還會停止相關的服務以及移除所有的Activity,並且會發送一個廣播。

注意一個問題:在android2.2之後,該方法不可以將應用程式結束,需要使用ActivityManager類的下面這個方法:

public void killBackgroundProcesses (String packageName)  

api 文檔說的很清楚:

public void restartPackage (String packageName)    Since: API Level 3  This method is deprecated.  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.  

另外,需要使用許可權:

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

但是不管你怎麼樣折騰,還是無法退出App,嗚呼哀哉!這裡給出一個方法:

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

關於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的生命週期方法。如:

System.exit(int);  onDestroy();  

 

android——徹底關閉——應用程式

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.