編輯:關於Android編程
1、安卓為什麼只能通過消息機制更新UI呢?
最根本的目的就是解決多線程並發問題。(多個線程同時執行一個任務)
假如在一個Activity中,有多個線程去更新UI,並且都沒有加鎖機制,那就會造成更新UI錯亂。如果對更新UI的操作都進行加鎖處理,就會造成性能下降。使用消息機制,根本不用關系多線程的問題,因為更新UI的操作,都是在主線程的消息隊列當中去輪詢處理的。
2、Handler是什麼?
Handler是android提供的一套更新UI的機制,也是消息處理機制,我們可以用它發送消息,也可以通過它處理消息。
更新UI,傳遞消息,處理消息。
3、默認情況下Handler會與其被定義時所在線程的Looper綁定,比如,Handler在主線程中定義,那麼它是與主線程的Looper綁定。
注意Handler的構造函數,New Handler()什麼參數都不需要
/** * Created on 2016/9/23. * Author:crs * Description:測試消息機制:主要用於線程間通訊,注意Handler類的構造函數 * 1)一個完整的消息要包括消息標識和消息內容.(消息對象裡面包含消息消息標識和消息內容;如果是空消息,只有消息標識沒有消息體) * * 2)只有在原生線程(主線程)才能更新UI,在子線程更新UI會報錯。 * * 3)使用消息機制更新UI的模板性代碼:創建Handler實例,在子線程中調用post方法,就兩步操作。 * handler.post(r): r是要執行的任務代碼,意思就是說r的代碼實際是在UI線程執行的,可以寫更新UI的代碼。 * * 4)使用消息機制更新UI的模板性代碼:創建Handler實例,重寫handleMessage()方法,創建消息對象並進行信息傳遞即可。 * obtainMessage() Message類 arg1 arg2 sendMessage(message實例) sendToTarget(); sendEmptyMessage() * * 5)使用消息機制實現圖片輪播:創建Handler實例,創建Runnable接口實例,調用postDelayed(runnable實例,毫秒值); * removeCallbacks(Runnable),就這幾步常規的操作 * * 6)創建Handler的時候,指定callBack;可以通過CallBack截獲Handler傳遞的消息. */
案例一:安卓中更新UI的四種方式
package com.crs.demo.ui.handler; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.widget.Button; import android.widget.TextView; import com.crs.demo.R; import com.crs.demo.base.BaseActivity; /** * Created on 2016/10/9. * Author:crs * Description:安卓中四種更新UI的方式 * 1)handler.post() * 2)handler.sendMessage() * 3)runOnUIThread() * 4)View.post */ public class TestUpdateUIActivity extends BaseActivity { private static final int SUCCESS_GET_DATA = 1; private Handler mHandler = new Handler(); private Handler myHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case SUCCESS_GET_DATA: { tv_activity_test_update_ui.setText("使用handler.sendMessage()更新"); } break; } } }; private TextView tv_activity_test_update_ui; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test_update_ui); initViews(); } private void initViews() { tv_activity_test_update_ui = findView(R.id.tv_activity_test_update_ui); Button btn_test_handler1 = findView(R.id.btn_test_handler1); Button btn_test_handler2 = findView(R.id.btn_test_handler2); Button btn_test_handler3 = findView(R.id.btn_test_handler3); Button btn_test_handler4 = findView(R.id.btn_test_handler4); //第一種方式:在子線程中調用runOnUIThread()更細UI btn_test_handler1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new Thread(new Runnable() { @Override public void run() { runOnUiThread(new Runnable() { @Override public void run() { tv_activity_test_update_ui.setText("調用runOnUIThread方法更新"); } }); } }).start(); } }); //第二種方式:使用View的post()更新UI btn_test_handler2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { tv_activity_test_update_ui.post(new Runnable() { @Override public void run() { tv_activity_test_update_ui.setText("使用View的post()更新UI"); } }); } }); //第三種方式:使用Handler的post()更新UI btn_test_handler3.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new Thread(new Runnable() { @Override public void run() { mHandler.post(new Runnable() { @Override public void run() { tv_activity_test_update_ui.setText("Handler的post()更新UI"); } }); } }).start(); } }); //第四種方式:使用Handler的sendMessage()更新UI btn_test_handler4.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new Thread(new Runnable() { @Override public void run() { //Message message = new Message(); //Message message = myHandler.obtainMessage(); myHandler.sendEmptyMessage(SUCCESS_GET_DATA); } }).start(); } }); } }案例二:攔截Handler傳遞的消息
package com.crs.demo.ui.handler; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.widget.Button; import com.crs.demo.R; import com.crs.demo.base.BaseActivity; import com.crs.demo.utils.ToastUtils; /** * Created on 2016/10/8. * Author:crs * Description:測試創建Handler指定CallBack */ public class TestCallBackActivity extends BaseActivity { private Handler mHandler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message msg) { //可以通過CallBack截獲Handler傳遞的消息,返回值表示是否截獲消息,false表示不截獲。 ToastUtils.showShort(TestCallBackActivity.this, "1"); //如果設置為true,就表示截獲消息,後面的handleMessage()就不在繼續執行了,即2不會被打印了。 return false; } }) { @Override public void handleMessage(Message msg) { ToastUtils.showShort(TestCallBackActivity.this, "2"); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test_call_back); initViews(); } private void initViews() { Button btn_activity_test_call_back = findView(R.id.btn_activity_test_call_back); btn_activity_test_call_back.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mHandler.sendEmptyMessage(1); } }); } }案例三:使用Handler實現圖片輪播效果
package com.crs.demo.ui.handler; import android.os.Bundle; import android.os.Handler; import android.widget.ImageView; import com.crs.demo.R; import com.crs.demo.base.BaseActivity; /** * Created on 2016/10/8. * Author:crs * Description:使用消息機制實現圖片輪播效果 * 關鍵是練習消息機制的使用 */ public class TestPostDelayedActivity extends BaseActivity { int[] image = {R.drawable.iv_1, R.drawable.iv_2, R.drawable.iv_3}; int index; private ImageView iv_test_post_delayed; //1)創建Handler實例 private Handler mHandler = new Handler(); //2)創建Runnable實例 private MyRunnable myRunnable = new MyRunnable(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test_post_delayed); iv_test_post_delayed = findView(R.id.iv_test_post_delayed); //3)調用此方法實現定時器效果 mHandler.postDelayed(myRunnable, 1000); } //實現接口 class MyRunnable implements Runnable { @Override public void run() { index++; //余數只有三種類型0、1、2 index = index % 3; //每隔多少秒要做的事(業務邏輯) iv_test_post_delayed.setImageResource(image[index]); mHandler.postDelayed(this, 1000); } } @Override protected void onPause() { super.onPause(); //清除此定時器效果 mHandler.removeCallbacks(myRunnable); } }案例四:自定義與線程相關的handler
package com.crs.demo.ui.handler; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; import com.crs.demo.R; import com.crs.demo.base.BaseActivity; import com.crs.demo.utils.LogUtils; /** * Created on 2016/10/9. * Author:crs * Description:自定義與線程相關的Handler */ public class TestCustomHandlerActivity extends BaseActivity { private static final String TAG = "TestCustomHandler"; private MyThread myThread; //創建主線程Handler private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); LogUtils.i(TAG, Thread.currentThread() + "主線程"); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test_custom_handler); myThread = new MyThread(); myThread.start(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } //主線程中的Handler mHandler.sendEmptyMessage(1); //子線程中的Handler myThread.myHandler.sendEmptyMessage(2); } class MyThread extends Thread { private Handler myHandler; @Override public void run() { super.run(); Looper.prepare(); myHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); LogUtils.i(TAG, Thread.currentThread() +"子線程"); } }; Looper.loop(); } } }
Handler的原理是什麼?
1)Handler封裝了消息的發送,主要包括消息發送給誰。
2)Looper:內部包含一個消息隊列,也就是MessageQueue,所有Handler發送的消息都會走向這個消息隊列。
Looper類中有一個loop()方法,它不斷的從MessageQueue中取消息,如果有消息就處理消息,如果沒有消息就阻塞。
3)MessageQueue就是一個消息隊列,可以添加消息、移除消息。
4)Handler內部會和Looper進行關聯,在Handler內部可以找到Looper。使用Handler發送消息,其實就是向MessageQueue隊列中發送消息。
總結:handler負責發送消息,Looper負責接收Handler發送的消息,並直接發消息傳回給handler自己、MessageQueue就是一個存儲消息的容器、looper是循環器。
消息標識與消息內容(int類型和對象類型)
如何獲取一個Message對象?
Handler的兩種作用:發送消息、傳遞消息.
Message與Handler之間的關系 sendToTarget()
Handler移除一個事件,停止事件的執行removeCallBack(runnable實例)
發送一個空消息的目的是什麼原理是什麼
截獲Handler發送的消息 new CallBack()
傳統的 登陸界面總有那些 點擊發送驗證碼然後等待接受的一個計時操作,今天就上一個類似的實現(不用傳統方法咯)先看下效果:貌不驚人,我們先來看看傳統的Handl
最近在項目開發中遇到一個關於手機輸入鍵盤的坑,特來記錄下。應用場景:項目中有一個界面是用viewpaper加三個fragment寫的,其中viewpaper被我屏蔽了左右
本文實例講述了Android編程實現調用系統分享功能。分享給大家供大家參考,具體如下:/** * 調用系統的分享功能 * Created by admin on 15-4
前言:上篇中介紹OMX事件回調,從今天開始,走入Codec部分之OpenMAX框架裡。看下今天的Agenda如下:一張圖回顧音視頻同步 一張圖看清OpenMAX在Andr