編輯:關於android開發
昨天發表的博文講述了Android中,采用異步任務進行網絡請求的內容,在異步任務結束時,采用Handler機制通知原來的Activity進行界面更新,網友 traburiss指出,異步任務的onPostExecute已經在UI線程中了,再用Handler等於要到下一個UI運行周期才能執行,效率會降低不少,而且違反了異步任務的本意。感謝 traburiss的意見,他說得非常正確,我之所以用到Handler,是因為要在Android應用開發中引入消息總線的概念,想基於Handler來做,所以才使用了這個技術,看來是不恰當的。所以在本篇博文中,我把涉及消息總線實現部分,一起講出來,這樣就避免了網友的提出的問題。
首先介紹一下消息總線,消息總線指系統發生的事件,如收到用戶注冊成功的異步任務完成消息,系統將消息放到消息總線上,對這個消息感興趣的應用組件,可以訂閱這個消息總線,這樣當消息發生時,這些組件會得到通知,從而完成消應的操作。引入消息總線技術,其主要優點是可以實現組件間的松耦合,消息生產者不用關心哪個組件會使用這個消息,只需將產生的消息放到消息總線上即可。而消息消費者訂閱這個消息總線,當消息發生時,就可以進行相應的處理了。
我們先來看消息總線的實現機制,代碼如下所示:
public class WkyMessageBus { public static void prepareEventBus() { messageBus = new HashMap>(); // 將所有消息類型加到消息總線上 HashMap registerUserListeners = new HashMap (); messageBus.put( + WkyConstants.MSG_WHAT_REGISTER_USER, registerUserListeners); } public static void registerToMessageBus(int messageTypeId, String listenerName, Handler handler) { HashMap listeners = messageBus.get( + messageTypeId); listeners.put(listenerName, handler); } public static void unregisterToMessageBus(int messageTypeId, String listenerName) { HashMap listeners = messageBus.get( + messageTypeId); listeners.remove(listenerName); } public static void postMessage(Message msg) { HashMap handlers = messageBus.get( + msg.what); for (Handler handler : handlers.values()) { handler.sendMessage(msg); } } private static HashMap > messageBus = null; }
如上面代碼所示,用messageBus來代表消息總線的集合,Android的Message對象的what值變為字符串作為key,其值為一個列表,列表元素為Handler,通過該handler可以向Activity發送消息,通知相應Activity進行相關操作。
Activity通過registerToMessageBus方法,訂閱到消息總線。在Activity銷毀時調用unregisterToMessageBus方法,從消息總線上注銷。
消息生產者產生消息後,通過postMessage將消息發布到消息總線上來。
在應用啟動時,即應用的Application對象的onCreate方法中,初始化消息總線。
WkyMessageBus.prepareEventBus();
如上篇文章所述,當異步任務結束時,會發送消息到消息總線:
/** * 異步任務結束時要調用的方法,通知頁面進行更新 * 【闫濤 2015.09.24】初始版本 */ @Override protected void onPostExecute(String result) { JSONObject json = null; long userId = 0; try { json = new JSONObject(result); userId = json.getLong(userId); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } WkyRegisterLoginModel model = (WkyRegisterLoginModel)activity.getModel(); model.setUserId(userId); activity.onAsyncTaskResult(); Message msg = handler.obtainMessage(); msg.what = WkyConstants.MSG_WHAT_REGISTER_USER; Bundle params = new Bundle(); params.putString(WkyConstants.MSG_DATA_NAME, result); msg.setData(params); WkyMessageBus.postMessage(msg); }
JysRegisterLoginActivity在啟動時,注冊到消息總線上去,在銷毀時從消息總線注銷,代碼如下所示:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(com.weikangyun.wkylib.R.layout.activity_register_login); handler = new JysRegisterLoginHandler(this); messageBusListenerName = this.getClass().getCanonicalName() + System.currentTimeMillis(); WkyMessageBus.registerToMessageBus(WkyConstants.MSG_WHAT_REGISTER_USER, messageBusListenerName, handler); getViewObjects(); setupGuis(); setupActionListeners(); } @Override public void onDestroy() { super.onDestroy(); WkyMessageBus.unregisterToMessageBus(WkyConstants.MSG_WHAT_REGISTER_USER, messageBusListenerName); }
static protected class JysRegisterLoginHandler extends WkyRegisterLoginHandler { public JysRegisterLoginHandler(JysRegisterLoginActivity activity) { this.activity = activity; } public void handleMessage(Message msg) { super.handleMessage(msg); // 自己額外的處理 switch (msg.what) { case WkyConstants.MSG_WHAT_REGISTER_USER: activity.processRegisterUserResult(msg); break; } } private JysRegisterLoginActivity activity = null; }
/** * 當異步任務完成後,會回調本方法,執行具體的頁面更新操作。需要實現兩部分功能: * 1. 異步任務:在onPostExecute函數中,將結果放到Activity對應的Model中 * 2. Activity中:從Model中取出數據,更新界面 * 【闫濤 2015.12.04】初始版本 */ public void onAsyncTaskResult() { }
這裡在補充一個問題,我們的網絡請求為什麼采用異步任務,而不是直接采用線程技術呢?是因為異步任務封裝了線程與UI線程之間的交互嗎?其實這只是其中的一個方面。因為在異步任務背後,是系統管理的線程池,系統會根據CPU核數,當前負載等因素,給出合適的線程解決方案(啟動新線程還是復用老線程)。而自己啟動線程的方案,由於不能獲取上述信息,所以不可能進行任何系統級的優化。因此,建議在能用異步任務的情況下,還是盡量用異步任務來解決問題。
用Kotlin實現Android定制視圖(KAD 06),kotlinandroid作者:Antonio Leiva 時間:Dec 27, 2016 原文鏈接:https
BLE-NRF51822教程3-sdk程序框架剖析nordicBLE 技術交流群498676838本講為框架介紹,不會牽涉到太多代碼細節。 51822的官方SDK其實是
重寫MPAndroidChart顯示標記 MPAndroidChart是實現圖表功能的優秀控件, 可以完成大多數繪制需求. 對於修改第三方庫而言, 優秀的架構是繼承開發,
界面優化處理技術之(三)登錄框表格組件優化處理,表格組件 在res下drawable下創建xml文件 代碼: 1 <?xml version=1.0 encodi