Android Handler
来源:互联网 发布:淘宝汽车装饰用品 编辑:程序博客网 时间:2024/06/04 17:40
Hanlder简介
相比于 AsyncTask,Handler类允许准确的控制操作的运行时间,而且还可以多次使用,执行的操作会一直运行,直到被显示的停止。每个Handler实例都被包含在一个单独的线程里面。
Handler 有两个主要的用途 :
1. 确保一些调度信息和任务在未来的某一时刻被执行
2. 让一些行为在其他的线程中表现出来
HandlerThread 介绍
HandlerThread 类用于创建一个带有 Looper 的新线程,这个Looper可以用于创建Handler 实例,HandlerThread 的实例必须在调用start() 方法后才可以使用。
构造方法 :
1. HandlerThread(String name)
2. HandlerThread (String name, int priority) //priority 就是线程运行的优先级,由 Process类中的变量 来指定
方法 :
1. getLooper ()
这个方法用于获取与该线程相关联的 Looper,如果该线程没有开启,也即未调用 start() 方法,那么这个方法会返回一个 null 值。如果线程已经开启,这个方法会被阻塞直到 Looper 初始化完成。
- getThreadId ()
用于返回线程的标识符
- quit ()
停止线程中的Looper,该方法被调用后,任何对Looper 的请求都会失败。比如,sendMessage(Message) 方法会返回false。使用这个方法可能是不安全的,因为在Looper被终止的时候可能还有 Message 未被递交。
- quitSafely ()
和上一个方法完成的功能相同,不过这个方法更安全,因为在Looper被终止时,一些未递交的 Message 会因为时间的关系不再递交。
- run ()
调用 Runnable 对象中的run() 方法,如果未设置Runnable,就什么也不做。
- onLooperPrepared ()
该方法是 protected 类型的,当我们需要在 Looper 的loop() 方法调用前需要完成一些工作,那么可以复写这个方法。
Looper 的简单介绍
Looper 类用来为线程运行 消息循环,默认的Threads 并不包含一个 message loop,为了创建一个,可以在线程中调用 prepare(),然后调用 loop() 去处理messages
官方给出的示例
class LooperThread extends Thread { public Handler mHandler; public void run() { Looper.prepare(); mHandler = new Handler() { public void handleMessage(Message msg) { // process incoming messages here } }; Looper.loop(); }
}
介绍一下Looper 类中的一些方法
- Looper getMainLooper ()
获得应用程序的主 Looper,存在于主线程中
- Thread getThread ()
返回与该 Looper 关联的 Thread
- void loop ()
在线程中运行 message queue,与此方法对应的是 quit() 方,而且这两个方法必须同时出现。
- Looper myLooper ()
返回与该线程关联的 Looper,如果该线程没有关联 Looper,就返回 null
- MessageQueue myQueue ()
返回与该线程关联的 MessageQueue,如果在未关联 Looper 的线程中调用该方法,会抛出 NullPointerException
- void prepare ()
初始化该线程作为一个Looper
- void quit ()
- void quitSafely()
功能和上面HandlerThread 中介绍的一样
异步消息处理机制
首先,在主线程中创建一个 Handler,并重写 handleMessage() 方法,然后当子线程需要进行 UI 操作时,就创建一个 Message 对象,并通过 Handler 将消息发送出去。之后这条消息会被添加到 MessageQueue 的队列中进行等待,而 Looper 会一直尝试从 MessageQueue 中取出待处理消息,最后分发回 Handler 的 handleMessage() 方法中。由于 Handler 是在主线程中创建的,此时的 handleMessage() 也会在主线程中得到执行。
一个Message 经过一个流程的辗转,从子线程进入到主线程,从不能更新 UI 到可以更新 UI,这就是异步消息处理机制的核心思想。
Hanlder 的简单使用
由于 Handler 中的方法太多,就不逐一介绍了,下面来介绍 几种给 Handler 发送信息的方法。
- Message.obtain(mHanlder,FLAG,data).sendToTarget()
创建一个标识为 FLAG,数据为 data 的Message,立刻将其发送到 Handler 去执行
- mHandler.sendEmptyMessage(FLAG)
立刻给 Handler 发送一个带有标识的空消息
- mHanlder.sendEmptyMessageAtTime(FLAG,1000)
给 Handler 发送一个简单的空消息,该消息会在一秒后被递交给 Looper
- mHandler.sendEmptyMessageDelayed(FLAG,1000)
效果同上
下面利用 Handler 来更改 UI
public class MainActivity extends AppCompatActivity {
public static final int FLAG = 0;private Button mButton;private TextView mTextView;private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { if (msg.what == FLAG) { mTextView.setText("After Changer"); } }};@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mButton = (Button) findViewById(R.id.start); mTextView = (TextView) findViewById(R.id.tx); mButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { new Thread(new Runnable() { @Override public void run() { mHandler.sendEmptyMessage(FLAG); } }).start(); } }); }}
注意,这个时候mHandler 使用的是默认 Looper,也即 MainLooper,我们也可以通过 HandlerThread 来使用自己的 Looper执行该操作。
public class MainActivity extends AppCompatActivity implements Handler.Callback {public static final int FLAG = 0;private Button mButton;private TextView mTextView;private HandlerThread mHandlerThread;private Handler mHandler;@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mHandlerThread = new HandlerThread("MyHandlerThread"); mHandlerThread.start(); mHandler = new Handler(mHandlerThread.getLooper(), this); mButton = (Button) findViewById(R.id.start); mTextView = (TextView) findViewById(R.id.tx); mButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { new Thread(new Runnable() { @Override public void run() { mHandler.sendEmptyMessage(FLAG); } }).start(); } });}@Overridepublic boolean handleMessage(Message message) { if (message.what == FLAG) { mTextView.setText("After Change"); } return true;}
}
这个时候会出现一个错误,因为我们自己的 Looper 是没有权限去更新 UI 的,如果想要更新 UI ,可以在 Handler 的构造方法中使用 getMainLooper() 方法。
以上我们都使用使用默认的 mHandler 和 HandlerThread,我们也可以写一个类继承自 HandlerThread 或者 Handler,在自定义的类中可以执行一些耗时任务,因为这个时候所有的任务都是在子线程中执行的,并不会阻塞主线程。
关于 AsyncTask 和 Handler 的选择,如果不是很频繁的执行一个操作,而且操作可以在较短时间内完成,使用 AsyncTask 是十分方便的。如果需要安排操作的时间或者需要快速间隔的执行某操作,Handler 是不错的选择。
- android Handler
- android Handler
- android Handler
- android Handler
- Android Handler
- android---handler
- android-handler
- Android Handler
- Android Handler
- Android Handler
- android Handler
- android--Handler
- Android Handler
- Android Handler
- Android Handler
- Android Handler
- Android handler
- Android Handler
- Android AsyncTask
- GeekBand C++学习笔记
- Spark简介
- 分类与回归
- Galaxy ZOO银河星空图的识别分类
- Android Handler
- algrothm_逆序输出(charAt+for+角标)
- 【ADB server didn't ACK||'adb.exe start-server' failed -- run manually if necessary】问题解决办法
- forward与redirect的区别
- Spring MVC数据转换的总结
- algrothm_n!(循环)
- 如何远程访问MySQL server?
- Java学习-8天
- SQL*LOADER操作篇