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。

 

    

 

 

 

   

posted @ 2015-02-16 14:42  scian  阅读(149)  评论(0)    收藏  举报