android 只有UI线程可以刷新界面,其他副线程不行,这样就需要副线程通过通信消息修改刷新和修改界面。

有2种方式可以实现:

AsyncTask,Handle

AsyncTask

android提供的简单用于异步通讯的线程,有句话,越完善的东西使用越麻烦。

主要四个实现接口:

onPreExecute(), 该方法将在执行实际的后台操作前被UI 线程调用。可以在该方法中做一些准备工作,如在界面上显示一个进度条,或者一些控件的实例化,这个方法可以不用实现。
doInBackground(Params...), 将在onPreExecute 方法执行后马上执行,该方法运行在后台线程中。这里将主要负责执行那些很耗时的后台处理工作。可以调用 publishProgress方法来更新实时的任务进度。该方法是抽象方法,子类必须实现。

onProgressUpdate(Progress...),在publishProgress方法被调用后,UI 线程将调用这个方法从而在界面上展示任务的进展情况,例如通过一个进度条进行展示。
onPostExecute(Result), 在doInBackground 执行完成后,onPostExecute 方法将被UI 线程调用,后台的计算结果将通过该方法传递到UI 线程,并且在界面上展示给用户.
onCancelled(),在用户取消线程操作的时候调用。在主线程中调用onCancelled()的时候调用。

调用注意

1) Task的实例必须在UI 线程中创建
2) execute方法必须在UI 线程中调用

3) 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法,需要在UI线程中实例化这个task来调用。
4) 该task只能被执行一次,否则多次调用时将会出现异常。(很久之前的资料,可能不准)

5)doInBackground方法返回值和onPostExecute的参数必须对应,这两个参数在AsyncTask声明的泛型参数列表中指定,第一个为doInBackground接受的参数,第二个为显示进度的参数,第第三个为doInBackground返回和onPostExecute传入的参数。

可以看到这个线程有副线程的接口处理doInBackground,也有UI线程的接口处理onProgressUpdate,在启动线程时可以传入泛类参数。

实战注意点:

继承 class MyThread extends AsyncTask<String, Integer, Integer> 泛类对应的3个接口泛类参数

protected Integer doInBackground(String... params)

protected void onProgressUpdate(Integer... values)

protected void onPostExecute(Integer result)

Handler

Handler类可以看做工具类,用来向消息队列中插入消息的。实例化时自动绑定调用的线程Looper,当处理消息时在该线程中执行。利用这个特性,副线程发送消息,接受消息后在主线程处理,达到主线程和副线程的通讯。

Looper类是用来封装消息循环和消息队列的一个类。

(1) Looper类用来为一个线程开启一个消息循环。
默认情况下android中新诞生的线程是没有开启消息循环的。(主线程除外,主线程系统会自动为其创建Looper对象,开启消息循环。)
Looper对象通过MessageQueue来存放消息和事件。一个线程只能有一个Looper,对应一个MessageQueue。

(2) 通常是通过Handler对象来与Looper进行交互的。Handler可看做是Looper的一个接口,用来向指定的Looper发送消息及定义处理方法。
默认情况下Handler会与其被定义时所在线程的Looper绑定,比如,Handler在主线程中定义,那么它是与主线程的Looper绑定。
mainHandler = new Handler() 等价于new Handler(Looper.myLooper()).
Looper.myLooper():获取当前进程的looper对象,类似的 Looper.getMainLooper() 用于获取主线程的Looper对象。

(3) 在非主线程中直接new Handler() 会报如下的错误:
E/AndroidRuntime( 6173): Uncaught handler: thread Thread-8 exiting due to uncaught exception
E/AndroidRuntime( 6173): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
原因是非主线程中默认没有创建Looper对象,需要先调用Looper.prepare()启用Looper。

(4) Looper.loop(); 让Looper开始工作,从消息队列里取消息,处理消息。
注意:写在Looper.loop()之后的代码不会被执行,这个函数内部应该是一个循环,当调用mHandler.getLooper().quit()后,loop才会中止,其后的代码才能得以运行。

(5) 基于以上知识,可实现主线程给子线程(非主线程)发送消息。
把下面例子中的mHandler声明成类成员,在主线程通过mHandler发送消息即可。

总结,一般都是绑定主线程的handler,达到通讯目的,在副线程中发送消息。若要创建副线程中绑定handler,则必须先创建副线程的looper,已达到循环发送消息的目的。有两种方式达到这个目的:

1、通过handler+Looper两个类。

2、通过HandlerThread这个类,这个是android提供的利用Looper和Handler继承Thread完成。

使用这个主意事项:

1、Looper.loop()导致run方法挂机,在收到消息时,会运行handler的handleMessage去处理消息。

2、在绑定Handler时需要判断Looper是否已经创建。

更多相关文章

  1. android的消息处理机制(图+源码分析)——Looper,Handler,Message (
  2. Android Push Notificatioin Service(Android消息推送)
  3. Android——消息机制中的Message Pool是个什么鬼,Message Pool会
  4. 解析 ViewTreeObserver 源码,体会观察者模式、Android消息传递(下)
  5. Android 开发艺术探索笔记(十五) 之 Android 的线程和线程池
  6. android消息推送-XMPP
  7. 使用GCM服务(Google Cloud Messaging)实现Android消息推送
  8. Android 事件处理基于Handler 消息处理
  9. Android学习笔记Android线程模型解析

随机推荐

  1. Android学习笔记(一)概述
  2. Android(安卓)中使用WebViewJavaScriptBr
  3. Android(安卓)Studio格式化代码设置和代
  4. 安卓混合开发——Android原生和H5数据交
  5. android sdcard存储方案(基于wrapfs文件系
  6. [Android]ListView性能优化之视图缓存
  7. Android SDK学习之
  8. 【笔记】【备忘】Android studio中更换AP
  9. 銆婃繁鍏ユ祬鍑篏oogle Android銆嬪嵆灏
  10. Android方向传感器实践——自己动手做指