Android Handler

Hanlder简介

相比于 AsyncTaskHandler类允许准确的控制操作的运行时间,而且还可以多次使用,执行的操作会一直运行,直到被显示的停止。每个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初始化完成。

  1. getThreadId ()

用于返回线程的标识符

  1. quit ()

停止线程中的Looper,该方法被调用后,任何对Looper 的请求都会失败。比如,sendMessage(Message)方法会返回false。使用这个方法可能是不安全的,因为在Looper被终止的时候可能还有 Message未被递交。

  1. quitSafely ()

和上一个方法完成的功能相同,不过这个方法更安全,因为在Looper被终止时,一些未递交的Message会因为时间的关系不再递交。

  1. run ()

调用Runnable对象中的run()方法,如果未设置Runnable,就什么也不做。

  1. onLooperPrepared ()

该方法是protected类型的,当我们需要在Looperloop() 方法调用前需要完成一些工作,那么可以复写这个方法。

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 类中的一些方法

  1. Looper getMainLooper ()

获得应用程序的主Looper,存在于主线程中

  1. Thread getThread ()

返回与该Looper 关联的 Thread

  1. void loop ()

在线程中运行message queue,与此方法对应的是quit()方法,而且这两个方法必须同时出现。

  1. Looper myLooper ()

返回与该线程关联的 Looper,如果该线程没有关联 Looper,就返回 null

  1. MessageQueue myQueue ()

返回与该线程关联的 MessageQueue,如果在未关联Looper的线程中调用该方法,会抛出NullPointerException

  1. void prepare ()

初始化该线程作为一个Looper

  1. void quit ()
  2. void quitSafely()

功能和上面HandlerThread中介绍的一样

异步消息处理机制

首先,在主线程中创建一个 Handler,并重写 handleMessage()方法,然后当子线程需要进行 UI 操作时,就创建一个Message 对象,并通过 Handler 将消息发送出去。之后这条消息会被添加到 MessageQueue的队列中进行等待,而 Looper 会一直尝试从 MessageQueue 中取出待处理消息,最后分发回 HandlerhandleMessage() 方法中。由于 Handler是在主线程中创建的,此时的 handleMessage()也会在主线程中得到执行。

一个Message经过一个流程的辗转,从子线程进入到主线程,从不能更新 UI到可以更新UI,这就是异步消息处理机制的核心思想。

Hanlder 的简单使用

由于 Handler 中的方法太多,就不逐一介绍了,下面来介绍 几种给 Handler发送信息的方法。

  1. Message.obtain(mHanlder,FLAG,data).sendToTarget()

创建一个标识为FLAG,数据为 dataMessage,立刻将其发送到 Handler去执行

  1. mHandler.sendEmptyMessage(FLAG)

立刻给 Handler发送一个带有标识的空消息

  1. mHanlder.sendEmptyMessageAtTime(FLAG,1000)

Handler发送一个简单的空消息,该消息会在一秒后被递交给Looper

  1. 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");
        }
    }
};

@Override
protected 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;

@Override
protected 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();
        }
    });

}

@Override
public boolean handleMessage(Message message) {
    if (message.what == FLAG) {
        mTextView.setText("After Change");
    }
    return true;
}

}

这个时候会出现一个错误,因为我们自己的Looper 是没有权限去更新 UI的,如果想要更新UI ,可以在Handler的构造方法中使用 getMainLooper()方法。

以上我们都使用使用默认的mHandlerHandlerThread,我们也可以写一个类继承自HandlerThread或者Handler,在自定义的类中可以执行一些耗时任务,因为这个时候所有的任务都是在子线程中执行的,并不会阻塞主线程。

关于 AsyncTaskHandler的选择,如果不是很频繁的执行一个操作,而且操作可以在较短时间内完成,使用AsyncTask是十分方便的。如果需要安排操作的时间或者需要快速间隔的执行某操作,Handler 是不错的选择。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容