Android-完全退出當前應用程序-新公司學習到的細節

上家公司因為某些原因離職了,于是每天出去面試也沒時間來寫我的博客了,這兩天結束了十來天的動蕩,算是穩定下來了,又重新拾起紙筆,寫上兩筆。

看公司代碼的時候就在想,一個維護了兩年的項目勢必是有他獨特的地方的,于是乎,在很多小細節的地方,以前雖然也面試準備過,可是確實沒寫過。這些東西,可能看起來不起眼,平時沒什么用,可能在某些時候避免了程序崩潰的危險呢。

比如,今天就實踐一個退出很多Activity的功能,在某些情況下保證安全。


借鑒一篇博客中的例子吧:(注冊流程)

如果一個交互流程中,是從A開始,按照A - B - C - D - A這樣的順序進行的話,那么B,C,D這3個活動界面會根據你D中最后的操作來進行保留或是摧毀,例如

(1)注冊流程中,在A界面點擊注冊,通過B,C,D界面完成注冊后,B,C,D就隨之摧毀,而如果D中注冊不成功沒跳轉會A的話,那么B,C,D就不能摧毀,之前所填的內容也必須保留。

(2)客戶端交互中,返回首頁按鈕,由于在頻繁的點擊打開過多的界面(如微信查看朋友圈),返回首頁就必須一個一個back回去,所有有的客戶端為了優化用戶體驗,便會加入一個按鈕返回首頁(之前打開的全部關閉)。


以上例子都涉及到了 --- 如何安全退出多個ACTIVITY 這個問題。

其實,這個問題的解決方案有好多種,并且各有各的優缺點,下面就羅列出多個方案以及各個方案的優缺點所在,以及本人所在項目采用的方案。


1. Dalvik VM的本地方法

android.os.Process.killProcess(android.os.Process.myPid()) //獲取PID
System.exit(0); //常規java、c#的標準退出法,返回值為0代表正常退出

2. 任務管理器方法

首先要說明該方法運行在Android 1.5 API Level為3以上才可以,同時需要權限

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

系統會將,該包下的 ,所有進程,服務,全部殺掉,就可以殺干凈了,要注意加上

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

3. 我們知道Android的窗口類提供了歷史棧,我們可以通過stack的原理來巧妙的實現,這里我們在A窗口打開B窗口時在Intent中直接加入標 志 Intent.FLAG_ACTIVITY_CLEAR_TOP,這樣開啟B時將會清除該進程空間的所有Activity。

思路:通過Intent的Flags來控制堆棧去解決
android中,每打開一個Activity,便會在棧中加入一個Activity,當該Activity被摧毀后,棧中便移除了它,并且棧中的Activity是按照開打的先后順序依次排排列的。
Android的窗口類提供了歷史棧,我們可以通過stack的原理來巧妙的實現,這里我們在A窗口打開B窗口時在Intent中直接加入標 志 Intent.FLAG_ACTIVITY_CLEAR_TOP,這樣開啟B時將會清除該進程空間的所有Activity。

btn_finish.setOnClickListener(new OnClickListener() {  
  
    @Override  
    public void onClick(View v) {  
        // TODO Auto-generated method stub  
        Intent intent = new Intent(INTENT_METHOD_FIRST_SINGUP);  
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);  
        startActivity(intent);  
    }  
});  

其中的 INTENT_METHOD_FIRST_SINGUP 是登錄界面的Intent隱式Action。

優缺點:
優:使用對棧的巧妙利用,不會造成內存無故占用等問題


4.自定義一個Actiivty 棧,道理同上,不過利用一個單例模式的Activity棧來管理所有Activity。并提供退出所有Activity的方法。代碼如下:

   public class ScreenManager {
 private static Stack<Activity> activityStack;
 private static ScreenManager instance;
 private  ScreenManager(){
 }
 public static ScreenManager getScreenManager(){
  if(instance==null){
   instance=new ScreenManager();
  }
  return instance;
 }
//退出棧頂Activity
 public void popActivity(Activity activity){
  if(activity!=null){
   activity.finish();
   activityStack.remove(activity);
   activity=null;
  }
 }

//獲得當前棧頂Activity
 public Activity currentActivity(){
  Activity activity=activityStack.lastElement();
  return activity;
 }

//將當前Activity推入棧中
 public void pushActivity(Activity activity){
  if(activityStack==null){
   activityStack=new Stack<Activity>();
  }
  activityStack.add(activity);
 }
 //退出棧中所有Activity
 public void popAllActivityExceptOne(Class cls){
  while(true){
   Activity activity=currentActivity();
   if(activity==null){
    break;
   }
   if(activity.getClass().equals(cls) ){
    break;
   }
   popActivity(activity);
  }
 }
}

5.全局記錄打開的Activity或通過一個自定義的類去管理打開的Activity

思路:通過在Application中用一個列表來記錄當前所打開的Activity,根據需求去遍歷finish()。

public class AppApplication extends Application {  
    private static AppApplication mAppApplication;  
    /** 當前打開的activity列表 */  
    public ArrayList<Activity> activityList;  
  
    @Override  
    public void onCreate() {  
        // TODO Auto-generated method stub  
        super.onCreate();  
        mAppApplication = this;  
    }  
  
    /** 獲取Application */  
    public static AppApplication getApp() {  
        if (mAppApplication == null) {  
            mAppApplication = new AppApplication();  
        }  
        return mAppApplication;  
    }  
  
    /** 添加當前Activity 到列表中 */  
    public void addActivity(Activity acitivity) {  
        if(activityList == null){  
            activityList = new ArrayList<Activity>();  
        }  
        activityList.add(acitivity);  
    }  
      
    /** 清空列表,取消引用*/  
    public void clearActivity(){  
        activityList.clear();  
    }  
  
    /** 遍歷退出所有Activity */  
    public void exit() {  
        for (Activity activity : activityList) {  
            activity.finish();  
        }  
        clearActivity();//千萬記得清空取消引用。  
        System.exit(0);  
    }  

優缺點:
缺:如果處理不當,容易造成不在當前界面的Activity被全局引用而摧毀不掉,內存得不到釋放,從而無故占用不必要的內存。


6.使用廣播機制解決

通過Activity創建的時候,設置監聽廣播,在注冊流程最后步完成注冊時候,發送廣播進行遍歷finish().

代碼:

/** 
 * 初始化退出廣播 
 */  
public void initFinishReceiver() {  
    IntentFilter filter = new IntentFilter();  
    filter.addAction(INIENT_FINISH);  
    registerReceiver(mFinishReceiver, filter);  
}  
  
/** 
 * 監聽是否退出的廣播 
 */  
public BroadcastReceiver mFinishReceiver = new BroadcastReceiver() {  
  
    @Override  
    public void onReceive(Context context, Intent intent) {  
        if (INIENT_FINISH.equals(intent.getAction())) {  
            finish();  
        }  
    }  
};  
在流程中的每步Activity中,初始化廣播,之后在點擊完成注冊時候,發送廣播
[java] view plain copy 在CODE上查看代碼片派生到我的代碼片
btn_finish.setOnClickListener(new OnClickListener() {  
  
    @Override  
    public void onClick(View v) {  
        // TODO Auto-generated method stub  
        getApplicationContext().sendBroadcast(new Intent(INIENT_FINISH));  
    }  
});  

缺:開啟過多的廣播監聽,覺得會浪費資源。

我這邊采用第三種方法,如下

public void exit() {
        Intent intent = new Intent();
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        intent.setClass(this, HomePageActivity.class);
        intent.putExtra("exitApp", true);
        
        Misc.startActivity(intent);
    }
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,546評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,570評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,505評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,017評論 1 313
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,786評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,219評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,287評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,438評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,971評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,796評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,995評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,540評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,230評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,662評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,918評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,697評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,991評論 2 374

推薦閱讀更多精彩內容