2015年6月28日 星期日

Android-使用單例模式(Singleton Pattern)關閉所有開啟過的Activity

在開發Android的App時,常會發生進入後台的Activity沒有正確的被關閉,還停留在後台繼續耗用系統的資源及消耗電量,或是按Back鍵時後台的Activity又回到前台畫面中,無法順利地離開App。
經過一翻搜尋方法後,找到了這篇文:
Android之完美退出方法(2.1-2.2-2.3SDK版本測試通過)

其中提到了一個個覺得蠻不錯的方法,特在此紀錄下來。主要是利用單例模式(Singleton Pattern)的方式,利用一個生命週期與App週期一樣長的唯一類別來管理所有開啟過的Activity,在要離開App時利用此單例的類別將所有開啟過的類別全部關掉,再把自己關掉,確保所有的Activity都關掉。

此例中有三個Activity,分別為MainActivity、Activity2、Activity3,三個Activity的Layout如下,在畫面正中央都有一個TextView顯示現在的頁面,而右下角都有一個Button可跳轉到下一個Activity,而在MainActivity按下Back鍵後,會關掉曾開啟的Activity並將整個App關掉。

此例中建立了一個單例類別,名為ActivityManager,在整個App的生命週期這個類別只會存在一個,裡面有一個LinkedList<Activity>用來存放所有開啟過的Activity,在每個Activity的onCreate()方法裡取得ActivityManager的物件實體並呼叫addActivity()方法來將Activity交由ActivityManager管理。最後在MainActivity的onBackPressed()中取得ActivityManager的物件實體並呼叫closeAllActivity()方法關掉所有曾開啟的Activity並結束App應用程式。

以下為程式碼,相關說明都已寫在註解中;

  1. ActivityManager:
  2. package com.hugo.closeallactivitysingletontest;
    
    
    
    import android.app.Activity;
    
    import android.app.Application;
    
    
    
    import java.util.LinkedList;
    
    
    
    //用來管理所有Activity的單例類別
    
    public class ActivityManager extends Application{
    
    
    
        private static ActivityManager instance;
    
        //用來儲存Activity的LinkedList
    
        private LinkedList<Activity> activityList = new LinkedList<Activity>();
    
        //此類別無法使用普通的方法實例化
    
        private ActivityManager(){
    
            super();
    
        }
    
        //用來取得唯一實例物件的方法
    
        public static ActivityManager getInstance(){
    
            if (instance == null){
    
                instance = new ActivityManager();
    
            }
    
            return instance;
    
        }
    
        //用來加入要管理的Activity的方法
    
        public void addActivity(Activity activity){
    
            activityList.add(activity);
    
        }
    
        //用來關掉所有被管理的Activity的方法
    
        public void closeAllActivity(){
    
            for (Activity activity : activityList){
    
                //fininsh()將Activity推向後台,移出了Activity推疊,資源並沒有被
    
                //釋放,不會觸發onDestory(),但按Back鍵也會回到原Activity
    
                activity.finish();
    
            }
    
            System.exit(0);
    
        }
    
    }
    
  3. MainActivity:
  4. package com.hugo.closeallactivitysingletontest;
    
    
    
    import android.content.Intent;
    
    import android.support.v7.app.ActionBarActivity;
    
    import android.os.Bundle;
    
    import android.view.Menu;
    
    import android.view.MenuItem;
    
    import android.view.View;
    
    import android.widget.Button;
    
    import android.widget.Toast;
    
    
    
    
    
    public class MainActivity extends ActionBarActivity {
    
    
    
        @Override
    
        protected void onCreate(Bundle savedInstanceState) {
    
            super.onCreate(savedInstanceState);
    
            setContentView(R.layout.activity_main);
    
    
    
            //將此Activity加進ActivityManager裡管理
    
            ActivityManager.getInstance().addActivity(this);
    
    
    
            Button gotoActivity2Btn = (Button) findViewById(R.id.gotoActivity2Btn);
    
            gotoActivity2Btn.setOnClickListener(new Button.OnClickListener() {
    
                @Override
    
                public void onClick(View v) {
    
                    startActivity(new Intent(MainActivity.this,Activity2.class));
    
                }
    
            });
    
        }
    
    
    
        //按下Back鍵後,關掉所有的Activity再退出App
    
        @Override
    
        public void onBackPressed() {
    
            super.onBackPressed();
    
            //使用單例的ActivityManager關掉所有的Activity再退出App
    
            ActivityManager.getInstance().closeAllActivity();
    
        }
    
    
    
        @Override
    
        public boolean onCreateOptionsMenu(Menu menu) {
    
            // Inflate the menu; this adds items to the action bar if it is present.
    
            getMenuInflater().inflate(R.menu.menu_main, menu);
    
            return true;
    
        }
    
    
    
        @Override
    
        public boolean onOptionsItemSelected(MenuItem item) {
    
            // Handle action bar item clicks here. The action bar will
    
            // automatically handle clicks on the Home/Up button, so long
    
            // as you specify a parent activity in AndroidManifest.xml.
    
            int id = item.getItemId();
    
    
    
            //noinspection SimplifiableIfStatement
    
            if (id == R.id.action_settings) {
    
                return true;
    
            }
    
    
    
            return super.onOptionsItemSelected(item);
    
        }
    
    }
    
  5. Activity2:
  6. package com.hugo.closeallactivitysingletontest;
    import android.content.Intent;
    import android.support.v7.app.ActionBarActivity;
    import android.os.Bundle;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.widget.Button;
    import android.widget.Toast;
    public class Activity2 extends ActionBarActivity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_activity2);
    
            //將此Activity加進ActivityManager裡管理
    
            ActivityManager.getInstance().addActivity(this);
            Button gotoActivity3Btn = (Button) findViewById(R.id.gotoActivity3Btn);
            gotoActivity3Btn.setOnClickListener(new Button.OnClickListener() {
                @Override
                public void onClick(View v) {
                    startActivity(new Intent(Activity2.this, Activity3.class));
                }
            });
        }
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.menu_activity2, menu);
            return true;
        }
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            // Handle action bar item clicks here. The action bar will
            // automatically handle clicks on the Home/Up button, so long
            // as you specify a parent activity in AndroidManifest.xml.
            int id = item.getItemId();
            //noinspection SimplifiableIfStatement
            if (id == R.id.action_settings) {
                return true;
            }
            return super.onOptionsItemSelected(item);
        }
    }
    
  7. Activity3:
  8. package com.hugo.closeallactivitysingletontest;
    import android.content.Intent;
    import android.support.v7.app.ActionBarActivity;
    import android.os.Bundle;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.widget.Button;
    import android.widget.Toast;
    public class Activity3 extends ActionBarActivity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_activity3);
            //將此Activity加進ActivityManager裡管理
            ActivityManager.getInstance().addActivity(this);
            Button gotoActivity1Btn = (Button) findViewById(R.id.gotoActivity1Btn);
            gotoActivity1Btn.setOnClickListener(new Button.OnClickListener() {
                @Override
                public void onClick(View v) {
                    startActivity(new Intent(Activity3.this, MainActivity.class));
                }
            });
        }
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.menu_activity3, menu);
            return true;
        }
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            // Handle action bar item clicks here. The action bar will
            // automatically handle clicks on the Home/Up button, so long
            // as you specify a parent activity in AndroidManifest.xml.
            int id = item.getItemId();
            //noinspection SimplifiableIfStatement
            if (id == R.id.action_settings) {
                return true;
            }
            return super.onOptionsItemSelected(item);
        }
    }
    
最後附上源始碼下載:

沒有留言 :

張貼留言