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()