|
為什么要寫這篇文章? 網上有很多種退出方法,可實際上很多方法都不通用(在某個版本下可用,到了另一個版本就不行),或者方法的實際效果根本就和其描述不符(也不知道那些發(fā)帖的人測沒測試過)。 但我們的需求又確實存在。在某些情況下,我們需要在應用中打開多個Activity,但如果僅僅使用finish()方法就不能在需要的時候達到一次性退出的效果,自己作為一個Android退出問題的受害者,通過良久思考和實際測試,找到了一個比較不錯的,在2.1-2.2-2.3版本下都通用的完全退出方法(2.1版本也基本可以代表1.5~2.1版本)! PS:測試全部在模擬器環(huán)境下進行 我首先進行一下說明,下面兩種方法效果完全相同 1,android.os.Process.killProcess(android.os.Process.myPid()) ; (這是Dalvik VM的本地方法) 2,System.exit(0); (常規(guī)java、c#的標準退出法,返回值為0代表正常退出 ) 之后我的說明全部以android.os.Process.killProcess(android.os.Process.myPid()) 方法為準。 另外,我后邊所說的程序入口即為在AndroidManifest.xml中配置為如下語句的Activity <action android:name="android.intent.action.MAIN" />
下面開始我們的Android完美退出之旅: 先從網上的一段說明說起: A->B 所以,如果過程是A->B->C 則實際情況是:A為程序入口,C中調用killProcess(android.os.Process.myPid())操作將程序入口A和執(zhí)行該語句的Activity C都關閉,并重新啟動新的程序入口A(在Activity窗口歷史棧當中,舊A 被關閉,新A 仍然會被放置在 舊A 所在的棧位置,不會到達棧頂端)。 PS: 如果killProcess(android.os.Process.myPid())或System.exit(0)是在程序入口A處執(zhí)行,則是將入口A關閉,不會再開啟新的A.
有人要問了,B Activity呢? B還存在著,B Activity沒有被關閉。 如何解決這個問題? 首先說明一點 android.os.Process.killProcess(android.os.Process.myPid()) ;語句執(zhí)行之后,后邊的代碼都將不再執(zhí)行; 而finish();或startActivity(A.this,B.class);語句在執(zhí)行完成后仍舊會執(zhí)行后續(xù)的代碼。(使用Thread.sleep多次驗證,不用擔心finish()過后不能startActivity了,相反也一樣)。 所以,我們就可以充分利用這一點,既然finish();和startActivity(A.this,B.class);語句在執(zhí)行后仍然可以執(zhí)行后續(xù)代碼操作,那我們可以將之組合在一個代碼片段中,即 startActivity(new Intent(B.this, C.class)); 或 finish(); startActivity(new Intent(B.this, C.class)); 都是可以的,我們在B中使用該代碼段,既將B Activity關閉了,也打開了C Activity,之前的問題Done! 如果你還有D,E,F ... 那也一樣,在每次跳轉到下一個Activity時,將finish()一塊用上。使用這種方式,多余的Activity就能夠被關閉了。
最后 假設我們有下面一種需求,對上邊的內容進行總結: Activity的開啟過程為 1.Index --> 2.A_Activity --> 3.B_Activity --> 4.Index,在4.Index中實現退出,Index為程序入口。 Index
退出:就是最簡單的finish();
跳轉:也是最簡單的 startActivity(new Intent(Index.this, A_Activity.class));
A_Activity
退回到首界面:分兩種情況
1,需要Index更新(我的Index就有這個需求,首頁面色彩發(fā)生變化)
使用android.os.Process.killProcess(android.os.Process.myPid()) ;關閉自己和之前的Index,創(chuàng)建新的Index;
2,不需要新的Index,Index無變化
使用最簡單的finish(),并且效率還要高些。
跳轉:
finish();
startActivity(new Intent(A_Activity.this, C.class)); 關閉自身,開啟除 Index 之外的其它Activity。 B_Activity 操作與 A_Activity 相同。當然跳轉語句變成了 finish(); startActivity(new Intent(B_Activity.this, Index.class));
************************************************************************************************************* 上邊的內容就是這樣了,下面我再告訴你另外一種方法,可以實現不關閉中途的Activity,而是在后邊的操作中一次性關閉前邊開啟的所有Activity,可以滿足一些人通過按返回鍵返回上一個界面的要求! 通過Android的窗口類提供的歷史棧,巧妙利用stack的原理,我們在Intent中加入標志 Intent.FLAG_ACTIVITY_CLEAR_TOP。
Intent intent = new Intent(); intent.setClass(One.this, Two.class);
假定有如下需求: 1.Index --> 2.A_Activity --> 3.B_Activity 在3中設置 intent.setClass(B_Activity.this, Index.class); 跳轉后,程序會從棧頂逐個向后查找,直到找到棧中最近的Index,然后將這一路找到的Activity全部關閉,包括1、2、3(也就不需要像我先前的方法一路finish了,也保留了途中經過的Activity),最后再自動建一個新的Index Activity放到棧頂的位置,接下來在Index窗口中使用finish方法即可退出。 如果沒有理解,看這個例子: 如果3中設置的是 intent.setClass(B_Activity.this, A_Activity.class); 則是將2,3關閉,再新建一個4.A_Activity,棧中就變成了 1.Index --> 4.A_Activity,懂了吧! 值得注意的是,在下面的情況中 1.Index --> 2.A_Activity --> 3.B_Activity --> 4.Index --> 5.A_Activity 在5中使用intent.setClass(A_Activity.this, B_Activity.class); 結果不是 1.Index --> 2.A_Activity --> 6.B_Activity 而是 1.Index --> 2.A_Activity --> 3.B_Activity --> 4.Index --> 5.A_Activity --> 6.B_Activity,因為4(程序入口)的存在,所以5對棧的操作不會到達3,而是發(fā)現4、5中都沒有B_Activity后,沒有關閉任何Activity,只在棧頂端新建了一個6.B_Activity。 這也間接說明了Dalvik虛擬機的遍歷算法只進行到最近的程序入口,就認為后邊沒有該程序的Activity了。所以良好的Android編程習慣是,新建一個程序入口時,一定把老程序入口關掉,這也解釋了為什么用killProcess方法更新后的程序入口Index一定還是在棧中的老位置,而不是到棧頂端。
這個方法我挺喜歡。 ********************************************************************************************** 還有一種比較流行的Android經典完美退出方法,使用單例模式創(chuàng)建一個Activity管理對象,該對象中有一個Activity容器(具體實現自己處理,使用LinkedList等)專門負責存儲新開啟的每一個Activity,并且容易理解、易于操作,非常不錯! MyApplication類(儲存每一個Activity,并實現關閉所有Activity的操作) public class MyApplication extends Application {
} public void exit() for(Activity activity:activityList) System.exit(0); } 在每一個Activity中的onCreate方法里添加該Activity到MyApplication對象實例容器中 MyApplication.getInstance().addActivity(this); 在需要結束所有Activity的時候調用exit方法 MyApplication.getInstance().exit();
有人反映,如果程序崩潰,可能會導致該類的被迫關閉并重建,使得前期放入的Activity無法正常關閉。
—————————————分割線————————————————— 我對其他一些退出方法進行的一點介紹和點評(不到之處還請指正): @restartPackage(getPackageName())(具體就不介紹了) 我在SDK2.1版本下開發(fā)的一款小軟件,放到Android2.2或2.3操作系統(tǒng)上無法退出,因為restartPackage方法在SDK2.1以后版本已經被廢棄不用了,理由是因為它不安全,可能關閉同其他應用程序共享的Service,而這個Service別人還要用呢,你給別人關了就不對了。
@有人說的終極退出方法: Intent startMain = new Intent(Intent.ACTION_MAIN); System.exit(0); 實際上這種方法只是返回了Home頁面,如果你再次進入應用,你會發(fā)現進入的首界面是你先前沒有關閉的Activity。
@調用系統(tǒng)隱藏forceStopPackage方法,這里是通過映射調用(也有其他方法) Method method = null; ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE); } 我在SDK2.2和2.3的測試結果是,出現NULLPointerException,彈出錯誤窗口,程序被迫關閉,和預想的正常退出有差別。不過我們可以通過修改基類實現自己的Thread.UncaughtExceptionHandler接口的uncaughtException方法,這樣就不會有錯誤窗口彈出。程序完全退出。
@和上面一樣,不過這是故意制造異常退出(上邊是無意制造的異常),但我認為這畢竟是下策。 引用鏈接:http://www./kaifafaq/670.html(制造異常退出方法) |
|
|