android的UI操作不是安全執行緒的,同時也只有主線程才能夠操作UI,同時主線程對於UI操作有一定的時間限制(最長5秒)。為了能夠做一些比較耗時的操作(比如下載、開啟大檔案等),android提供了一些列機制。《android基礎知識02——安全執行緒》系列文章就是參考了網上許多網友的文章後,整理出來的一個系列,介紹了主要的方法。分別如下:
android基礎知識02——安全執行緒1:定義及例子
android基礎知識02——安全執行緒2:handler、message、runnable
android基礎知識02——安全執行緒3:Message,MessageQueue,Handler,Looper
android基礎知識02——安全執行緒4:HandlerThread
android基礎知識02——安全執行緒5: AsyncTask
在前面介紹的安全執行緒中,為了操作主線程的UI,使用子線程進行處理。在android開發中,還可以使用另外兩種方法進行處理:
HandlerThread
AsyncTask
本文先介紹HandlerThread。
HandlerThread繼承於Thread,所以它本質就是個Thread。與普通Thread的差別就在於,它有個Looper成員變數。這個Looper其實就是對訊息佇列以及隊列處理邏輯的封裝,簡單說就是 訊息佇列+訊息迴圈。
當我們需要一個工作者線程,而不是把它當作一次性消耗品,用過即廢棄的話,就可以使用它。
其使用方法為:
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); HandlerThread hThread=new HandlerThread("myThread"); hThread.start(); myhandler myhandler=new myhandler(hThread.getLooper()); Message msg=myhandler.obtainMessage(); msg.sendToTarget();//把 Message發送到目標對象,目標對象就是產生msg的目標對象。 } class myhandler extends Handler{ public myhandler(Looper looper){ super(looper); } public void handleMessage(Message msg) { Log.e("這是新線程", "》》》》》》》》》》》》》》》》》新線程的測試"); } }
這裡通過HandlerThread啟動一個新線程。
註:這裡需要handlerThread.start();先啟動線程 才能 handlerThread.getLooper() 擷取當前線程的Looper。
HandlerThread使用是比較簡單的,我們翻翻它的源碼,也是很簡單的。
/** * Handy class for starting a new thread that has a looper. The looper can then be * used to create handler classes. Note that start() must still be called. */public class HandlerThread extends Thread { private int mPriority; private int mTid = -1; private Looper mLooper; public HandlerThread(String name) { super(name); mPriority = Process.THREAD_PRIORITY_DEFAULT; } /** * Constructs a HandlerThread. * @param name * @param priority The priority to run the thread at. The value supplied must be from * {@link android.os.Process} and not from java.lang.Thread. */ public HandlerThread(String name, int priority) { super(name); mPriority = priority; } /** * Call back method that can be explicitly over ridden if needed to execute some * setup before Looper loops. */ protected void onLooperPrepared() { } public void run() { mTid = Process.myTid(); Looper.prepare(); synchronized (this) { mLooper = Looper.myLooper(); Process.setThreadPriority(mPriority); notifyAll(); } onLooperPrepared(); Looper.loop(); mTid = -1; } /** * This method returns the Looper associated with this thread. If this thread not been started * or for any reason is isAlive() returns false, this method will return null. If this thread * has been started, this method will block until the looper has been initialized. * @return The looper. */ public Looper getLooper() { if (!isAlive()) { return null; } // If the thread has been started, wait until the looper has been created. synchronized (this) { while (isAlive() && mLooper == null) { try { wait(); } catch (InterruptedException e) { } } } return mLooper; } /** * Ask the currently running looper to quit. If the thread has not * been started or has finished (that is if {@link #getLooper} returns * null), then false is returned. Otherwise the looper is asked to * quit and true is returned. */ public boolean quit() { Looper looper = getLooper(); if (looper != null) { looper.quit(); return true; } return false; } /** * Returns the identifier of this thread. See Process.myTid(). */ public int getThreadId() { return mTid; }}