Android异步消息处理(一)--》Handler和多线程深入
2016-01-13 14:03
579 查看
不得不说大神的博客就是不一样,如果对Handler一点都不了解,可以先先看一下我的这里全面但是显得臃肿的内容。如果基础比较好,请参考大神的博客http://blog.csdn.net/lmj623565791/article/details/38377229
Android中的异步消息处理中Handler机制是一种很重要的机制
我们需要明白:
【1】Handler是什么?怎么用?为什么要用Handler
【2】android为什么要设计只能通过Handler机制更新UI呢
【3】Handler的原理是什么?
【4】使用Handler遇到的问题
【5】如何实现一个与线程相关的Handler
【6】HandlerThread又是什么呢
【7】如何在主线程给子线程发送消息呢
【8】android中更新UI的几种方式
【9】非UI线程真的不能更新UI呢?
一.什么是Handler,怎么用,为什么要用?
我们需要明确以下几点:
【1】Android更新UI(例如从网络下下载图片)不要阻塞UI线程
【2】不要在UI线程之外访问Android UI工具包
因为如果多个线程去更新UI,并且都没有加锁机制,会产生更新界面错乱。而加锁后性能又会下降。换一个思路:我们根本不用去关心多线程的问题,所有的更新UI操作,均在主线程的消息队列中去轮询处理。
Handler是android给我们提供的用来更新UI的一套机制,也是一套消息处理的机制,我们可以发送消息,也可以通过它处理消息。见下面一段例子,通过Handler发送一个消息,实现进行引导页3S后进入主页面。
实际上,我们的Activity的生命周期中,它是如何去根据不同的情况调用到onCreate(),onDestroy()等方法的呢?答案就是Handler机制,简单的理解就是通过handler发送消息,然后进行相应的处理。
Android在设计的时候,就封装了一套消息创建、传递、处理机制,如果不遵循这样的机制的话,就没有办法更新UI信息的,就会抛出异常信息。其实消息处理机制也可以自己设计,但是比较复杂。
Handler有以下几种发送消息的重要方法(其中的msg.what是消息对象Message msg的标识信息,通常为一个整型常量)
sendEmptyMessageDelayed(int msg.what, long delayMillis); //发送一个空消息
sendMessageAtTime(int msg.what, System.currentTimeMillis()+3000); //在一个特定时间发送,该例子为当前时间3s后,
sendMessageDelayed(int msg.what, 2000); //延迟2s后执行,上一段代码中有案例
post(Runable runable); //执行一个线程
postDelayed(Runable runable, long delayMillis); //延迟特定时间后执行某线程
handler.removeCallbacks(Runable runable); //移除线程。
handler.sendMessage(Message msg); //可以指定msg.what msg.obj(携带一个Object对象) msg.arg1 msg.arg2 (这两个参数可以携带一些整型数据)
例如下面的图片轮播
二.Handler原理
我们要清楚Handler异步消息处理的四大部分
1.Message 它是在线程之间传递的信息,用于在不同线程之间交换数据。
2.MessageQueue 消息队列,遵循先进先出原则,主要用于存放所有通过Handler发送的消息。每个线程中只会有一个MessageQueue对象。Android启动程序会在创建Looper时,在UI线程创建一个MessageQueue。Handler发送消息就是将消息添加到MessageQueue中
3.Handler 用于发送和处理消息的。
4.Looper 是每个线程MessageQueue的管家,调用Looper的loop()方法后,就会进入死循环,每当发现MessageQueue中有消息,就将它取出在传递会Handler的handleMessage()方法进行处理。Android启动程序会在创建Handler时,在UI线程创建一个Looper对象。每个线程中只有一个Looper对象。
总结:handler负责发送消息,将消息存储到MessageQueue中,Looper负责从MessageQueue中取出Handler发送的消息,并直接把消息回传给handler自己。
一个更形象的图:小孩子相当于Handler,它发送要上厕所的消息给教授,教授接收到消息后做了个回应“你去吧”,然后小孩子自己去完成上厕所的操作。
Android中的异步消息处理中Handler机制是一种很重要的机制
我们需要明白:
【1】Handler是什么?怎么用?为什么要用Handler
【2】android为什么要设计只能通过Handler机制更新UI呢
【3】Handler的原理是什么?
【4】使用Handler遇到的问题
【5】如何实现一个与线程相关的Handler
【6】HandlerThread又是什么呢
【7】如何在主线程给子线程发送消息呢
【8】android中更新UI的几种方式
【9】非UI线程真的不能更新UI呢?
一.什么是Handler,怎么用,为什么要用?
我们需要明确以下几点:
【1】Android更新UI(例如从网络下下载图片)不要阻塞UI线程
【2】不要在UI线程之外访问Android UI工具包
因为如果多个线程去更新UI,并且都没有加锁机制,会产生更新界面错乱。而加锁后性能又会下降。换一个思路:我们根本不用去关心多线程的问题,所有的更新UI操作,均在主线程的消息队列中去轮询处理。
Handler是android给我们提供的用来更新UI的一套机制,也是一套消息处理的机制,我们可以发送消息,也可以通过它处理消息。见下面一段例子,通过Handler发送一个消息,实现进行引导页3S后进入主页面。
static class SplashHandler extends Handler { WeakReference<SplashActivity> splashActivityWeakReference; SplashHandler(SplashActivity activity) { splashActivityWeakReference = new WeakReference<SplashActivity>(activity); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); SplashActivity activity = splashActivityWeakReference.get(); switch (msg.what) { case START_MAIN_ACTIVITY: SharedPreferences settings = activity.getSharedPreferences(Config.PREFERENCES_FILE_NAME, MODE_PRIVATE); isFirstRun = settings.getBoolean(FIRST_RUN, true); if (isFirstRun) { activity.startActivity(new Intent(activity, GuideActivity.class)); } else { activity.startActivity(new Intent(activity, com.touch.zjzplayer.activity.MainActivity.class)); } activity.finish(); break; } } }在onCreate()方法中:
SplashHandler handler = new SplashHandler(this); handler.sendEmptyMessageDelayed(START_MAIN_ACTIVITY, 3000);
实际上,我们的Activity的生命周期中,它是如何去根据不同的情况调用到onCreate(),onDestroy()等方法的呢?答案就是Handler机制,简单的理解就是通过handler发送消息,然后进行相应的处理。
Android在设计的时候,就封装了一套消息创建、传递、处理机制,如果不遵循这样的机制的话,就没有办法更新UI信息的,就会抛出异常信息。其实消息处理机制也可以自己设计,但是比较复杂。
Handler有以下几种发送消息的重要方法(其中的msg.what是消息对象Message msg的标识信息,通常为一个整型常量)
sendEmptyMessageDelayed(int msg.what, long delayMillis); //发送一个空消息
sendMessageAtTime(int msg.what, System.currentTimeMillis()+3000); //在一个特定时间发送,该例子为当前时间3s后,
sendMessageDelayed(int msg.what, 2000); //延迟2s后执行,上一段代码中有案例
post(Runable runable); //执行一个线程
postDelayed(Runable runable, long delayMillis); //延迟特定时间后执行某线程
handler.removeCallbacks(Runable runable); //移除线程。
handler.sendMessage(Message msg); //可以指定msg.what msg.obj(携带一个Object对象) msg.arg1 msg.arg2 (这两个参数可以携带一些整型数据)
例如下面的图片轮播
<pre name="code" class="java">public class TestActivity extends Activity{ private Handler handler = new Handler(); private int[] imgs = {R.drawable.guide_pager_one, R.drawable.guide_pager_two, R.drawable.guide_pager_three}; private int index; private ImageView img; private MyRunable myRunable = new MyRunable(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); img = (ImageView) findViewById(R.id.img); handler.postDelayed(myRunable, 2000); } class MyRunable implements Runnable { @Override public void run() { img.setImageResource(imgs[index]); index++; index = index % 3; handler.postDelayed(myRunable, 2000); } } //点击按钮,关闭轮播 public void closeRunnable(View view) { handler.removeCallbacks(myRunable); } }资源文件:
<pre name="code" class="html"><?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="关闭轮播" android:onClick="closeRunnable"/> <ImageView android:id="@+id/img" android:layout_width="100dp" android:layout_height="200dp" /> </LinearLayout>还有一种用法是拦截不合法的消息,在Handler构造函数中有一个是Handler handler = new Handler(Callback callback); 例如下面代码:
public class TestActivity extends Activity{ private Handler handler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message msg) { Toast.makeText(TestActivity.this, ""+1, Toast.LENGTH_SHORT).show(); return false; //false表示没有拦截,true表示已经拦截,就不会执行下面的handleMessage()方法 } }){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); Toast.makeText(TestActivity.this, ""+2, Toast.LENGTH_SHORT).show(); } }; private int[] imgs = {R.drawable.guide_pager_one, R.drawable.guide_pager_two, R.drawable.guide_pager_three}; private int index; private ImageView img; private MyRunable myRunable = new MyRunable(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); img = (ImageView) findViewById(R.id.img); handler.postDelayed(myRunable, 2000); } class MyRunable implements Runnable { @Override public void run() { img.setImageResource(imgs[index]); index++; index = index % 3; handler.postDelayed(myRunable, 2000); } } //点击按钮,关闭轮播 public void closeRunnable(View view) { handler.removeCallbacks(myRunable); handler.sendEmptyMessage(0); } }
二.Handler原理
我们要清楚Handler异步消息处理的四大部分
1.Message 它是在线程之间传递的信息,用于在不同线程之间交换数据。
2.MessageQueue 消息队列,遵循先进先出原则,主要用于存放所有通过Handler发送的消息。每个线程中只会有一个MessageQueue对象。Android启动程序会在创建Looper时,在UI线程创建一个MessageQueue。Handler发送消息就是将消息添加到MessageQueue中
3.Handler 用于发送和处理消息的。
4.Looper 是每个线程MessageQueue的管家,调用Looper的loop()方法后,就会进入死循环,每当发现MessageQueue中有消息,就将它取出在传递会Handler的handleMessage()方法进行处理。Android启动程序会在创建Handler时,在UI线程创建一个Looper对象。每个线程中只有一个Looper对象。
总结:handler负责发送消息,将消息存储到MessageQueue中,Looper负责从MessageQueue中取出Handler发送的消息,并直接把消息回传给handler自己。
一个更形象的图:小孩子相当于Handler,它发送要上厕所的消息给教授,教授接收到消息后做了个回应“你去吧”,然后小孩子自己去完成上厕所的操作。
相关文章推荐
- Android ADB命令大全(通过ADB命令查看wifi密码、MAC地址、设备信息、操作文件、查看文件、日志信息、卸载、启动和安装APK等)
- android数据存储方法总结
- android 下载apk源码
- android中延迟执行某个任务
- 【Android动画】之Tween动画 (渐变、缩放、位移、旋转)
- This Handler class should be static or leaks might occur Android
- 从.NET的宠物商店到Android MVC MVP
- 阅读《Android 从入门到精通》(10)——单项选择
- android上的缓存、缓存算法和缓存框架
- Android退出应用最优雅的方式(改进版)
- [Android] Android开发优化之——对Bitmap的内存优化
- android 简单试题系统
- android studio开发中遇到的问题收集
- Android中使用log4j
- Android Studio——\\转义
- 使用Android Studio遇到的问题
- Android中EditText 的setInputType以及setRawInputType区别
- SourceTree提交AndroidManifest.xml文件
- Activity启动模式
- Android之MVP设计模式