Android Short Tips:Handler附着在UI线程上的创建方式
不管在App开发中,还是在Framework源码里面,随处可见Handler,而且Handler基本都是与UI线程相关联。对于刚接触Android开发的童鞋来说,很容易有一个误解:Handler就是附着的UI线程上的。其实不是这样,Handler与哪个线程关联依赖与Handler的创建上下文环境,Handler也是可以附着在后台线程的。由于在实践中主要都是在UI线程上,下面简要介绍一下让Handler附着在UI线程的创建方式。
-
UI线程创建Handler
如果当前的上下文就在UI线程,譬如,Application的onCreate中、Activity各生命周期中、View的创建过程中、View的各类点击事件中等等,在这些环境中如果没有特殊的数学处理需求,只需要直接创建:
package com.scian.handlerdemo;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
public class MainActivity extends Activity {
private Handler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 直接创建
mHandler = new Handler();
}
}
这样Handler自然就附着在UI线程上了,可以随便使用。
-
非UI线程上创建Handler
绝大多数Android应用,都会开启后台线程,常见的模式如后台处理数据,结束后在UI上展现数据。如果使用Handler来完成数据的交互,就得在后台线程上下文中保持一个附着在UI线程上的Handler的引用。这有两种方式可以实现:
-
Handler在外部UI线程中创建,然后注入到后台线程的上下文中;
这种方式最为常见,但一个不好的地方是导致后台线程环境对UI线程对象的依赖,在一定程度上破坏了封闭性。
-
Handler直接在非UI线程内部创建,但此Handler仍旧附着在UI线程上;
我自己更倾向于这种方式,它既能满足使用需求,又保证了对象的独立性和封闭性。将Handler附着在UI线程的关键是找到UI线程上的Looper对象,Handler支持基于Looper对象的构造,如:
private Handler createHandler() {
Handler handler = null;
Looper looper = Looper.myLooper(); // 获取当前线程上线文的Looper对象,注意,可能为null
Looper mainLooper = Looper.getMainLooper();// 获取UI线程的Looper对象,一般不会为null
if (mainLooper.equals(looper)) { // UI线程
handler = new Handler();
} else { // 非UI线程
handler = new Handler(mainLooper);
}
return handler;
}
这样,在后台线程环境对象内部就可以保留一个UI线程的Handler ,后台过程结束后,通过Handler可以安全更新UI。
浙公网安备 33010602011771号