android開發 之 Bolts-Android
目錄
多執行緒程式設計對比: iOS與Android
android的多執行緒程式設計有
Thread
Handler
AsyncTask
IntentService
android多執行緒詳細可以參考
iOS的多執行緒程式設計有
NSthread
GCD
NSOperationQueue
iOS多執行緒詳細可以參考 / /
對比兩個平臺的多執行緒程式設計, android還是稍遜一些
Handler和IntentService的多執行緒程式設計, 開銷有些大, 而GCD配合Block, 簡潔好用並且功能也很強大
AsyncTask處理訊息佇列和多執行緒同步, 是比較費勁的, 而NSOperationQueue, 仍然是簡單好用五顆星
那有沒有一種方案可以讓android變得和iOS一樣簡單好用呢?
答案就是今天的主角
Bolts-Android
Bolts-Android由"榮譽"出品, 為什麼說是"榮譽"呢?
因為作為Baas的鼻祖, Parse已經成功地死在了沙灘上, 但是被Facebook關門之後, 它仍然發揮了餘熱, Parse的很多專案都在上開源了
廢話不多說, 直接看例子吧
Tasks
想要在當前執行緒執行Task, 就是這麼簡單
Task.call(new Callable() { @Override public Boolean call() throws Exception { XLog.d(Thread.currentThread().getName() + " " + "call in current thread"); return true; } });
如果想在後臺執行緒執行Task
Task.callInBackground(new Callable() { @Override public Boolean call() throws Exception { XLog.d(Thread.currentThread().getName() + " " + "call in background thread"); return true; } });
如果想在UI主執行緒執行Task
Task.call(new Callable() { @Override public Boolean call() throws Exception { XLog.d(Thread.currentThread().getName() + " " + "call in main thread"); return true; } }, Task.UI_THREAD_EXECUTOR);
如果想要延時執行Task
Task.delay(2000).continueWith(new Continuation() { @Override public Void then(Task task) throws Exception { XLog.d(Thread.currentThread().getName() + " " + "call in main thread (after delay 2 seconds)"); return null; } });
是不是簡單到讓人無法相信? 其實這裡的Task和iOS中的GCD程式設計是類似的(詳細可以參考)
Chaining Tasks
熱完身, 我們來看下Bolts-Android的函數語言程式設計(關於函數語言程式設計詳細可以參考)
Task.call(new Callable() { @Override public Boolean call() throws Exception { XLog.d(Thread.currentThread().getName() + " calling"); return true; } }, Task.UI_THREAD_EXECUTOR).continueWith(new Continuation () { @Override public String then(Task task) throws Exception { Thread.sleep(2000); XLog.d(Thread.currentThread().getName() + " onSuccess " + task.getResult()); return "hello bolts"; } }, Task.BACKGROUND_EXECUTOR).continueWith(new Continuation () { @Override public Void then(Task task) throws Exception { XLog.d(Thread.currentThread().getName() + " continueWith " + task.getResult()); return null; } }, Task.UI_THREAD_EXECUTOR);
列印結果如下
main calling pool-2-thread-1 onSuccess truemain continueWith hello bolts
透過函式式的鏈式程式設計, 輕鬆地實現了Task的同步和多執行緒的切換(怎麼忽然就想到了了呢? 看來下期可以來個Bolts-Android大戰RxJava的專題)
Group Tasks
Group Task是我取得名字哈, 所謂Group Tasks, 就是指多個Task組成的一組Tasks
Task.call(new Callable() { @Override public Boolean call() throws Exception { XLog.d(Thread.currentThread().getName() + " calling"); return true; } }, Task.UI_THREAD_EXECUTOR).continueWith(new Continuation >>() { @Override public List > then(Task task) throws Exception { XLog.d(Thread.currentThread().getName() + " tasks start"); List > tasks = new ArrayList >(); tasks.add(asyncOperation1()); tasks.add(asyncOperation2()); Task.whenAll(tasks).waitForCompletion(); XLog.d(Thread.currentThread().getName() + " tasks end"); return tasks; } }, Task.BACKGROUND_EXECUTOR).continueWith(new Continuation >, Void>() { @Override public Void then(Task
>> task) throws Exception { XLog.d(Thread.currentThread().getName() + " done"); return null; } }, Task.UI_THREAD_EXECUTOR);
其中asyncOperation1和asyncOperation2的定義如下
private TaskasyncOperation1() { return Task.callInBackground(new Callable () { @Override public Void call() throws Exception { XLog.i("asyncOperation1 start"); try { Thread.sleep(1000); } catch (Exception e) { XLog.e(e.getMessage()); } XLog.i("asyncOperation1 end"); return null; } }); }private Task asyncOperation2() { return Task.callInBackground(new Callable () { @Override public Void call() throws Exception { XLog.i("asyncOperation2 start"); try { Thread.sleep(3000); } catch (Exception e) { XLog.e(e.getMessage()); } XLog.i("asyncOperation2 end"); return null; } }); }
後面的continueWith會等asyncOperation1和asyncOperation2都執行完成後再執行
列印結果如下
main calling pool-2-thread-1 tasks start asyncOperation1 start asyncOperation2 start asyncOperation1 end asyncOperation2 end pool-2-thread-1 tasks end main done
有沒有小試牛刀的感覺? 我們接著來看下面的用法
Tasks in Parallel
final Executor PARALLEL_EXECUTOR = Executors.newCachedThreadPool(); Task.call(new Callable() { @Override public Void call() throws Exception { for (int i = 0; i () { @Override public Void call() throws Exception { for (int i = 0; i 列印結果如下
pool-2-thread-1 i = 0 pool-2-thread-2 i = 50 pool-2-thread-1 i = 1 pool-2-thread-2 i = 51 pool-2-thread-1 i = 2 pool-2-thread-2 i = 52 pool-2-thread-1 i = 3 pool-2-thread-2 i = 53 pool-2-thread-1 i = 4 pool-2-thread-2 i = 54 pool-2-thread-1 i = 5 pool-2-thread-1 i = 6 pool-2-thread-2 i = 55 pool-2-thread-2 i = 56 pool-2-thread-1 i = 7 pool-2-thread-1 i = 8 pool-2-thread-2 i = 57 pool-2-thread-2 i = 58 pool-2-thread-1 i = 9 pool-2-thread-2 i = 59 pool-2-thread-1 i = 10 pool-2-thread-2 i = 60 pool-2-thread-1 i = 11 pool-2-thread-2 i = 61 pool-2-thread-1 i = 12 pool-2-thread-2 i = 62 pool-2-thread-1 i = 13 pool-2-thread-2 i = 63 pool-2-thread-1 i = 14 pool-2-thread-2 i = 64 pool-2-thread-1 i = 15 pool-2-thread-2 i = 65 pool-2-thread-1 i = 16 pool-2-thread-2 i = 66 pool-2-thread-1 i = 17 pool-2-thread-2 i = 67 pool-2-thread-1 i = 18 pool-2-thread-1 i = 19 pool-2-thread-2 i = 68 pool-2-thread-1 i = 20 pool-2-thread-2 i = 69 pool-2-thread-1 i = 21 pool-2-thread-2 i = 70 pool-2-thread-1 i = 22 pool-2-thread-2 i = 71 pool-2-thread-1 i = 23 pool-2-thread-2 i = 72 pool-2-thread-1 i = 24 pool-2-thread-2 i = 73 pool-2-thread-2 i = 74 pool-2-thread-1 i = 25 pool-2-thread-2 i = 75 pool-2-thread-1 i = 26 pool-2-thread-2 i = 76 pool-2-thread-1 i = 27 pool-2-thread-2 i = 77 pool-2-thread-1 i = 28 pool-2-thread-2 i = 78 pool-2-thread-1 i = 29 pool-2-thread-2 i = 79 pool-2-thread-1 i = 30 pool-2-thread-1 i = 31 pool-2-thread-2 i = 80 pool-2-thread-1 i = 32 pool-2-thread-2 i = 81 pool-2-thread-1 i = 33 pool-2-thread-2 i = 82 pool-2-thread-1 i = 34 pool-2-thread-2 i = 83 pool-2-thread-2 i = 84 pool-2-thread-1 i = 35 pool-2-thread-2 i = 85 pool-2-thread-1 i = 36 pool-2-thread-2 i = 86 pool-2-thread-1 i = 37 pool-2-thread-2 i = 87 pool-2-thread-1 i = 38 pool-2-thread-1 i = 39 pool-2-thread-2 i = 88 pool-2-thread-1 i = 40 pool-2-thread-2 i = 89 pool-2-thread-1 i = 41 pool-2-thread-2 i = 90 pool-2-thread-1 i = 42 pool-2-thread-2 i = 91 pool-2-thread-1 i = 43 pool-2-thread-2 i = 92 pool-2-thread-1 i = 44 pool-2-thread-2 i = 93 pool-2-thread-1 i = 45 pool-2-thread-2 i = 94 pool-2-thread-1 i = 46 pool-2-thread-2 i = 95 pool-2-thread-1 i = 47 pool-2-thread-2 i = 96 pool-2-thread-1 i = 48 pool-2-thread-2 i = 97 pool-2-thread-1 i = 49 pool-2-thread-2 i = 98 pool-2-thread-2 i = 99列印結果有兩個發現
執行緒池有兩個執行緒: pool-2-thread-1和pool-2-thread-2
執行緒池裡的執行緒是並行執行的: 數字都是
Tasks in Serial
那有沒有方法可以讓執行緒池中只有一個執行緒, 所有Tasks按照queue的方式FIFO依次執行呢? 辦法如下
final Executor SERIAL_EXECUTOR = Executors.newSingleThreadExecutor(); Task.call(new Callable() { @Override public Void call() throws Exception { for (int i = 0; i () { @Override public Void call() throws Exception { for (int i = 50; i 列印結果如下
pool-2-thread-1 i = 0 pool-2-thread-1 i = 1 pool-2-thread-1 i = 2 pool-2-thread-1 i = 3 pool-2-thread-1 i = 4 pool-2-thread-1 i = 5 pool-2-thread-1 i = 6 pool-2-thread-1 i = 7 pool-2-thread-1 i = 8 pool-2-thread-1 i = 9 pool-2-thread-1 i = 10 pool-2-thread-1 i = 11 pool-2-thread-1 i = 12 pool-2-thread-1 i = 13 pool-2-thread-1 i = 14 pool-2-thread-1 i = 15 pool-2-thread-1 i = 16 pool-2-thread-1 i = 17 pool-2-thread-1 i = 18 pool-2-thread-1 i = 19 pool-2-thread-1 i = 20 pool-2-thread-1 i = 21 pool-2-thread-1 i = 22 pool-2-thread-1 i = 23 pool-2-thread-1 i = 24 pool-2-thread-1 i = 25 pool-2-thread-1 i = 26 pool-2-thread-1 i = 27 pool-2-thread-1 i = 28 pool-2-thread-1 i = 29 pool-2-thread-1 i = 30 pool-2-thread-1 i = 31 pool-2-thread-1 i = 32 pool-2-thread-1 i = 33 pool-2-thread-1 i = 34 pool-2-thread-1 i = 35 pool-2-thread-1 i = 36 pool-2-thread-1 i = 37 pool-2-thread-1 i = 38 pool-2-thread-1 i = 39 pool-2-thread-1 i = 40 pool-2-thread-1 i = 41 pool-2-thread-1 i = 42 pool-2-thread-1 i = 43 pool-2-thread-1 i = 44 pool-2-thread-1 i = 45 pool-2-thread-1 i = 46 pool-2-thread-1 i = 47 pool-2-thread-1 i = 48 pool-2-thread-1 i = 49 pool-2-thread-1 i = 50 pool-2-thread-1 i = 51 pool-2-thread-1 i = 52 pool-2-thread-1 i = 53 pool-2-thread-1 i = 54 pool-2-thread-1 i = 55 pool-2-thread-1 i = 56 pool-2-thread-1 i = 57 pool-2-thread-1 i = 58 pool-2-thread-1 i = 59 pool-2-thread-1 i = 60 pool-2-thread-1 i = 61 pool-2-thread-1 i = 62 pool-2-thread-1 i = 63 pool-2-thread-1 i = 64 pool-2-thread-1 i = 65 pool-2-thread-1 i = 66 pool-2-thread-1 i = 67 pool-2-thread-1 i = 68 pool-2-thread-1 i = 69 pool-2-thread-1 i = 70 pool-2-thread-1 i = 71 pool-2-thread-1 i = 72 pool-2-thread-1 i = 73 pool-2-thread-1 i = 74 pool-2-thread-1 i = 75 pool-2-thread-1 i = 76 pool-2-thread-1 i = 77 pool-2-thread-1 i = 78 pool-2-thread-1 i = 79 pool-2-thread-1 i = 80 pool-2-thread-1 i = 81 pool-2-thread-1 i = 82 pool-2-thread-1 i = 83 pool-2-thread-1 i = 84 pool-2-thread-1 i = 85 pool-2-thread-1 i = 86 pool-2-thread-1 i = 87 pool-2-thread-1 i = 88 pool-2-thread-1 i = 89 pool-2-thread-1 i = 90 pool-2-thread-1 i = 91 pool-2-thread-1 i = 92 pool-2-thread-1 i = 93 pool-2-thread-1 i = 94 pool-2-thread-1 i = 95 pool-2-thread-1 i = 96 pool-2-thread-1 i = 97 pool-2-thread-1 i = 98 pool-2-thread-1 i = 99Error Handling
看完上面的內容, 想必各位從此都是android多執行緒的"磚家"了吧, 不過請稍等片刻, 還有一個重要的問題沒有解釋
Task.call(new Callable() { @Override public String call() throws Exception { Thread.sleep(2000); if (1 () { @Override public Void then(Task task) throws Exception { XLog.d(Thread.currentThread().getName() + " onSuccess"); return null; } }, Task.UI_THREAD_EXECUTOR).continueWith(new Continuation () { @Override public Void then(Task task) throws Exception { if (task.isFaulted()) { XLog.e(Thread.currentThread().getName() + " error"); return null; } XLog.d(Thread.currentThread().getName() + " done"); return null; } }, Task.UI_THREAD_EXECUTOR); 請問這裡的列印結果是如何呢?
A: onSuccess
B: error
C: done
D: onSuccess & done
正確答案是B
小結
android多執行緒的方案還有諸如: , 不過經過實測, 和Bolts-Android比較起來, android-priority-jobqueue還是"略重量級"了一些, 如果你有更好的方案和實現, 歡迎留言和分享
作者:諾之林
連結:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2144/viewspace-2802936/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Android API開發之OpenGL開發之Android OpenGL STL詳解AndroidAPI
- android 開發之 APT 技術AndroidAPT
- Android JNI開發系列之配置Android
- Android開發之常用佈局Android
- Android開發工具類之DownloadManagerProAndroid
- Android NDK開發之JNI基礎Android
- Mac之Android Studio開發NDK入門MacAndroid
- Android開發之指令碼替換PackageNameAndroid指令碼Package
- Android Native 開發之 NewString 與 NewStringUtf 解析Android
- Android開發之跟蹤應用更新大小Android
- Android之五大應用開發框架Android框架
- Android NDK 開發之 CMake 必知必會Android
- Android開發之執行緒間通訊Android執行緒
- Android JNI開發系列之Java與C相互呼叫AndroidJava
- react-native&android 之開發問題篇一ReactAndroid
- Android之NDK開發錯誤 error: unknown type name 'JNIEXPORT'AndroidErrorExport
- Android NDK開發之引入第三方庫Android
- Android開發之無侵入式修改TabLayout tabIndicator寬度AndroidTabLayoutIndicator
- Android 高質量開發之崩潰最佳化Android
- Android安全開發之淺談金鑰硬編碼Android
- Android開發之平板和橫豎屏適配-RecyclerViewAndroidView
- Android 開發感想Android
- Android開發之--visibility屬性VISIBLE、INVISIBLE、GONE的區別AndroidGo
- 【Android開發入門教程】四.使用者介面之LayoutAndroid
- 聚焦 Android 11: Android 開發者工具Android
- 【為生活開發系列之五】開源Android福彩號碼對比助手Android
- Android開發隨記Android
- Ndk 初步開發 In AndroidAndroid
- Android Camera開發指南Android
- Android開發筆記Android筆記
- Android開發 - Context解析AndroidContext
- Android Jetpack - Android TV 應用開發教程AndroidJetpack
- Android開發中Kotlin之於java那些不一樣的功能AndroidKotlinJava
- Android開發之監聽軟鍵盤狀態(彈出收回)Android
- Android開發之自定義隨機驗證碼控制元件Android隨機控制元件
- 搭建直播平臺,Android開發之禁止下拉通知欄的方法Android
- Android開發之從零開始學RxJava 2.x(一)認識RxjavaAndroidRxJava
- Java開發和Android開發的區別JavaAndroid