在介绍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:
这里稍微详细介绍一下Handler 其它几种都比较好理解。 可以参见Android简明开发教程十九:线程 Bezier曲线。
Android 在每个创建的Thread都可以有个与之关联的Message Queue,如果在这个Thread中创建Handler 对象,这个Handler 对象可以用来向创建它的Thread的Message Queue发送消息。比如在Main Thread(UI Thread)创建的Handler 可以用来个UI线程发送消息。
Handler 定义两类操作:
我们再来看看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更新操作。