Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android開發中無處不在的設計模式——單例模式

Android開發中無處不在的設計模式——單例模式

編輯:關於Android編程

對於開發人員來說,設計模式有時候就是一道坎,但是設計模式又非常有用,過了這道坎,它可以讓你水平提高一個檔次。而在android開發中,必要的了解一些設計模式又是非常有必要的。對於想系統的學習設計模式的同學,這裡推薦2本書。一本是Head First系列的Head Hirst Design Pattern,英文好的可以看英文,可以多讀幾遍。另外一本是大話設計模式。

這篇文章介紹一個模式,就是單例模式,因為個人覺得這個模式理解起來最容易,而且不是太復雜。

首先了解一些什麼是單例,從名字中就可以聽出來就是在內存中維護唯一對象。這樣做有以下幾個優點

對於那些比較耗內存的類,只實例化一次可以大大提高性能,尤其是在移動開發中。 保持程序運行的時候該中始終只有一個實例存在內存中

其實單例有很多種實現方式,但是個人比較傾向於其中1種。可以見單例模式

代碼如下

public class Singleton {
    private static volatile Singleton instance = null;

    private Singleton(){
    }

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

要保證單例,需要做一下幾步

必須防止外部可以調用構造函數進行實例化,因此構造函數必須私有化。 必須定義一個靜態函數獲得該單例 單例使用volatile修飾 使用synchronized 進行同步處理,並且雙重判斷是否為null,我們看到synchronized (Singleton.class)裡面又進行了是否為null的判斷,這是因為一個線程進入了該代碼,如果另一個線程在等待,這時候前一個線程創建了一個實例出來完畢後,另一個線程獲得鎖進入該同步代碼,實例已經存在,沒必要再次創建,因此這個判斷是否是null還是必須的。

至於單例的並發測試,可以使用CountDownLatch,使用await()等待鎖釋放,使用countDown()釋放鎖從而達到並發的效果。可以見下面的代碼

public static void main(String[] args) {
    final CountDownLatch latch = new CountDownLatch(1);
    int threadCount = 1000;
    for (int i = 0; i < threadCount; i++) {
        new Thread() {
            @Override
            public void run() {
                try {
                    latch.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Singleton.getInstance().hashCode());
            }
        }.start();
    }
    latch.countDown();
}

看看打印出來的hashCode會不會出現不一樣即可,理論上是全部都一樣的。

而在Android中,很多地方用到了單例。

比如Android-Universal-Image-Loader中的單例

private volatile static ImageLoader instance;
/** Returns singleton class instance */
public static ImageLoader getInstance() {
    if (instance == null) {
        synchronized (ImageLoader.class) {
            if (instance == null) {
                instance = new ImageLoader();
            }
        }
    }
    return instance;
}

比如EventBus中的單例

private static volatile EventBus defaultInstance;
public static EventBus getDefault() {
    if (defaultInstance == null) {
        synchronized (EventBus.class) {
            if (defaultInstance == null) {
                defaultInstance = new EventBus();
            }
        }
    }
    return defaultInstance;
}

上面的單例都是比較規規矩矩的,當然實際上有很多單例都是變了一個樣子,單本質還是單例。

如InputMethodManager 中的單例

static InputMethodManager sInstance;
public static InputMethodManager getInstance() {
    synchronized (InputMethodManager.class) {
        if (sInstance == null) {
            IBinder b = ServiceManager.getService(Context.INPUT_METHOD_SERVICE);
            IInputMethodManager service = IInputMethodManager.Stub.asInterface(b);
            sInstance = new InputMethodManager(service, Looper.getMainLooper());
        }
        return sInstance;
    }
}

AccessibilityManager 中的單例,看代碼這麼長,其實就是進行了一些判斷,還是一個單例

private static AccessibilityManager sInstance;
public static AccessibilityManager getInstance(Context context) {
    synchronized (sInstanceSync) {
        if (sInstance == null) {
            final int userId;
            if (Binder.getCallingUid() == Process.SYSTEM_UID
                    || context.checkCallingOrSelfPermission(
                            Manifest.permission.INTERACT_ACROSS_USERS)
                                    == PackageManager.PERMISSION_GRANTED
                    || context.checkCallingOrSelfPermission(
                            Manifest.permission.INTERACT_ACROSS_USERS_FULL)
                                    == PackageManager.PERMISSION_GRANTED) {
                userId = UserHandle.USER_CURRENT;
            } else {
                userId = UserHandle.myUserId();
            }
            IBinder iBinder = ServiceManager.getService(Context.ACCESSIBILITY_SERVICE);
            IAccessibilityManager service = IAccessibilityManager.Stub.asInterface(iBinder);
            sInstance = new AccessibilityManager(context, service, userId);
        }
    }
    return sInstance;
}

當然單例還有很多種寫法,比如惡漢式,有興趣的自己去了解就好了。

最後,我們應用一下單例模式。典型的一個應用就是管理我們的Activity,下面這個可以作為一個工具類,代碼也很簡單,也不做什麼解釋了。

= 0; i--) {
            Activity activity = mActivityStack.get(i);
            activity.finish();
        }

        mActivityStack.clear();
        android.os.Process.killProcess(android.os.Process.myPid());
    }
}
 data-snippet-id=ext.608f66d10fdff6ed00efbc7f1da79657 data-snippet-saved=false data-csrftoken=FYnEyihx-HThe5yDZmYHxN69KoghnvlRVy8E data-codota-status=done>public class ActivityManager {

    private static volatile ActivityManager instance;
    private Stack mActivityStack = new Stack();

    private ActivityManager(){

    }

    public static ActivityManager getInstance(){
        if (instance == null) {
        synchronized (ActivityManager.class) {
            if (instance == null) {
                instance = new ActivityManager();
            }
        }
        return instance;
    }

    public void addActicity(Activity act){
        mActivityStack.push(act);
    }

    public void removeActivity(Activity act){
        mActivityStack.remove(act);
    }

    public void killMyProcess(){
        int nCount = mActivityStack.size();
        for (int i = nCount - 1; i >= 0; i--) {
            Activity activity = mActivityStack.get(i);
            activity.finish();
        }

        mActivityStack.clear();
        android.os.Process.killProcess(android.os.Process.myPid());
    }
}

這個類可以在開源中國的幾個客戶端中找到類似的源碼

Git@OSC中的AppManager

android-app中的AppManager

以上兩個類是一樣的,沒區別。

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved