android入門:zxing學習筆記(五)

來源:互聯網
上載者:User

     莫道君行早,更有早行人。     

     Barcode Scanner不只是上面兩篇說的這麼簡單,還有其他處理,如閃光燈,放大處理,最優的預覽尺寸等等。這些不影響對代碼的理解,知道camera的使用後,開始看看Barcode Scanner是如何高效的進行識別處理的。在android檔案夾下,就有一個thread類:DecodeThread,兩個handler類:CaptureActivityHandler和DecodeHandler。在沒有認真看兩個類時,一直以為這兩個handler是理所當然的方式,以為自己就知道了。後面發現不是這麼簡單,尤其是DecodeThread的實現是android 中背景工作執行緒的經典實現。

     在Barcode Scanner中,有著繁多的訊息傳送,處理的訊息的handler也有兩個。如何將訊息傳送到指定的handler中去,從代碼上看挺清晰的,將message和指定的handler綁定。前面提到過,在android中有主線程和背景工作執行緒之分。Activity這類的main thread,還有自己建立的work thread,如果要更新UI,則需要再main thread中進行處理,可以通過handler來實現訊息傳遞,將訊息送到main thread的訊息佇列去。

     Barcode Scanner中有兩個Thread 和 兩個handler,在這四個類中通過加入這樣的語句判斷他們thread中得關係:

1 System.out.println(TAG + "The worker thread id = " +   Thread.currentThread().getId()); //判斷線程ID

     最後啟動並執行結果:

1 01-12 02:41:12.594: I/System.out(655): CaptureActivity The main thread id = 1
2 01-12 02:41:14.605: I/System.out(655): CaptureActivityHandler The handler thread id = 1
3 01-12 02:41:12.946: I/System.out(655): DecodeThread The worker thread id = 13
4 01-12 02:41:13.094: I/System.out(655): DecodeHandler The handler thread id = 13

    由此可見,這兩個handler都分別屬於他們的thread。但在建立這兩個handler時,有很大的差別。CaptureActivityHandler的建立只是簡簡單單的new了,沒有其他輔助。這就是main activity在建立時,系統預設為它建立一個looper,負責管理該線程的訊息迴圈,取送訊息等,不需要額外指定。但對於自己建立的Thread,系統預設是沒有為其建立looper的,需要自己為它建立訊息迴圈。

    先看下DecodeThread的代碼 : 去掉了跟理解線程不相關的代碼。

 1 final class DecodeThread extends Thread {
2 public static String TAG = DecodeThread.class.getSimpleName();
3 private final CaptureActivity activity;
4 private Handler handler;
5 private final CountDownLatch handlerInitLatch;//到計數的鎖
6 DecodeThread(CaptureActivity activity,
7 Vector<BarcodeFormat> decodeFormats,
8 String characterSet,
9 ResultPointCallback resultPointCallback) {
10
11 this.activity = activity;
12 handlerInitLatch = new CountDownLatch(1);//從1開始到計數
13
14 }
15
16 Handler getHandler() {
17 try {
18 handlerInitLatch.await();//阻塞先等handler被初始化了才能返回結果。改計數鎖即等countdown-->0。
19 } catch (InterruptedException ie) {
20 // continue?
21 }
22 return handler;
23 }
24
25 @Override
26 public void run() {
27 Looper.prepare();
28 handler = new DecodeHandler(activity, hints);
29 handlerInitLatch.countDown();//啟動到計數,countdown-1 變成0;
30 System.out.println(TAG + "The worker thread id = " + Thread.currentThread().getId()); //判斷線程ID
31 Looper.loop();
32 }

    前面定義了一個CountDownLatch類型變數,該變數為一個倒計數用的鎖。用法挺簡單,如代碼中,先new CountDownLatch(1),計數值為1, handlerInitLatch.countDown(), 開始倒數。handlerInitLatch.await() 若計數值沒有變為0,則一直阻塞。直到計數值為0後,才return handler,因此在調用getHandler時不會返回null的handler。

    在建立DecodeThread線程的handler時,首先線上程中調用Looper.prepare()來建立訊息佇列,再建立附於該線程的handler對象,最後調用Looper.loop()進入訊息迴圈,這個這個loop()迴圈不會立馬返回,需要自己主動調用Looper.myLooper().quit()才會返回。這就是自己建立一個背景工作執行緒,為其分配一個訊息佇列,訊息迴圈的簡單迅速辦法。

    前面說到camera的自動聚焦,只是隔斷時間週期性不停向CaptureActivityHandler發送自動聚焦請求,這就是一個訊息傳送:

1 Message message = autoFocusHandler.obtainMessage(autoFocusMessage, success);
2 autoFocusHandler.sendMessageDelayed(message, AUTOFOCUS_INTERVAL_MS);

     這樣建立了訊息,隔斷時間發送。

     關於Android的訊息處理機制,這裡有篇更好的文章,請點這裡。還有這一篇介紹looper的。這兩篇說的更透徹,實用。這還發現一篇巨作。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.