`
lyunabc
  • 浏览: 529524 次
  • 性别: Icon_minigender_2
社区版块
存档分类
最新评论

Android 系统Handler用法简介

 
阅读更多

在介绍ApiDemo中的Service示例之前有必要对Android的线程做个说明。

在Application启动后,Android系统会为这个应用创建一主线程(Main Thread),主线程负责把消息分发给相应的UI控件,并处理屏幕绘制事件,因此主线程也被称为UI 线程,事件的处理是通过一个称为“Event Queue”来分发的。比如,按下屏幕上某个按钮后,UI 线程将会把“Touch”事件通知该按钮,按钮接受到这个“Touch”事件将其状态设为“按下”状态,并向Event Queue中添加一个“Invalidate”事件表示该按钮需要重绘。 UI线程会定时从Event Queue取出请求事件并通知按钮重绘。

当应用启动后,缺省情况下只有一个Main Thread在运行,如果应用设计得不好的话,这种单线程模型可能会导致应用程序性能很差。特别是如果所有的操作都发生在这个UI线程中,比如一些费时的操作如网络操作,数据库访问将会阻塞UI线程,造成应用程序不响应用户输入,严重的情况Android将显示ANR (应用程序无响应)对应框,强制应用程序退出。

所以设计一个及时响应用户的应用的一个基本原则是:永远不要阻塞UI线程,如果你有一些费时的操作,启动一个工作线程(worker thread)来完成。

使用工作线程时如果需要更新UI ,需要注意的是,目前大部分系统UI 都是设计成单线程模式的,也就是说UI 组件定义的操作不是”Thread -Safe”的,不能直接在非UI线程(如工作线程)中更新UI。幸运的是Android系统提供多种类或方法来实现从非UI线程中更新UI:

  • Activity.runOnUiThread(Runnable)
  • View.post(Runnable)
  • View.postDelayed(Runnable, long)
  • Handler
  • AsyncTask

这里稍微详细介绍一下Handler 其它几种都比较好理解。 可以参见Android简明开发教程十九:线程 Bezier曲线。

Android 在每个创建的Thread都可以有个与之关联的Message Queue,如果在这个Thread中创建Handler 对象,这个Handler 对象可以用来向创建它的Thread的Message Queue发送消息。比如在Main Thread(UI Thread)创建的Handler 可以用来个UI线程发送消息。

Handler 定义两类操作:

  • 一是定义在未来的某个时刻执行某个操作(Runnables) ,这主要是通过调用post(Runnable), postAtTime(Runnable, long), postDelayed(Runnable, long) 来完成。
  • 二是在别的Thread的Event Queue添加一个操作,以便在该Thread中执行,这主要通过调用sendEmptyMessage(int), sendMessage(Message), sendMessageAtTime(Message, long)来完成。

我们再来看看AdvancedPreferences 中与Handler相关的代码:

private Handler mHandler = new Handler();

mHandler 定义在 AdvancedPreferences ,AdvancedPreferences 为PreferenceActivity的子类 (UI组件), mHandler 因此与UI Thread 的Message Queue关联,可以用来给UI线程发送消息或是Schedule 一个Runnable 以便在 UI 线程中执行。


private Runnable mForceCheckBoxRunnable = new Runnable() {
public void run() {
if (mCheckBoxPreference != null) {
mCheckBoxPreference.setChecked(!mCheckBoxPreference.isChecked());
}

// Force toggle again in a second
mHandler.postDelayed(this, 1000);
}
};


上面代码定义了一个Runnable 对象,其中代码mHandler.postDelayed(this, 1000); 给UI线程Message Queue发送一个请求:每隔1秒钟执行自己,切换mCheckBoxPreference的状态并再次请求1秒执行同样操作。 UI 线程 定时从Message Queue中取出事件来执行 (更新 Checkbox 在UI线程中),这样就实现了从非UI线程中执行UI更新操作。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics