`
gaosililn
  • 浏览: 73408 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

Android系列学习:handler,HandlerThread

阅读更多

android 系列学习之 Handler

handler是啥?handler的定义:主要接受子线程发送的数据,并用此数据配合更新UI。 Handler的使用: 曾经学过Java的同学都知道,以前在Java当中,要不断的更新JFrame上面的信息,可以再一个子线程当中直接更新,但是在Android当中呢?有人会说,Android主要也是使用Java的,可以跟Java一样实现。但事实并不是。Android的机制处理中,处于线程安全,Android是出了名的单一线程实例。

 

Log.e("threadID", Thread.currentThread().getId() + "");
 textView = (TextView) this.findViewById(R.id.textView);
 new Thread() {
 @Override 
public void run() {
 super.run();
 try { sleep(3000);
 Log.e("ThreadID", Thread.currentThread().getId() + ""); textView.setText("newTHread"); 
} catch (InterruptedException e) {
 e.printStackTrace();
 } 
}
 }.start();
 

 

  看上面的代码,在Java当中运行时没有一点儿问题的。但是在Android的平台当中确是不行的(在有的机测试确实可以的,这个原因有有待研究),会抛出下列异常:android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 那么怎么解决这个问题呢?常用的方法就是使用handler处理。 代码改一下:

 

protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
 Log.e("threadID——main", Thread.currentThread().getId() + ""); 
textView = (TextView) this.findViewById(R.id.textView); handler.post(runnable); 

}
 Handler handler = new Handler(); 
Runnable runnable = new Runnable() { 
@Override 
public void run() {
 Log.e("threadID--runnable",Thread.currentThread().getId()+""); textView.setText("TextViewSetText");
 }
 };
 

 

 问题是解决了,但是呢又有新的问题出来了,分别在main Runnable中都打印出来当前线程的ID,但是呢打印出来的结果却是  id是一样的!是一样的!!是一样的!!!此刻你是不是也都凌乱了?或许这情况只是在main中调用的只是run()而已,并非启动runnable子线程。(原因后面继续跟进) 不少同学在使用一些APP时候,都会发现其中他们的图片会不定时的切换。怎么实现呢?其实使用handler也是挺简单的一件事情。 图片的前置条件

 

private int images[] = {R.drawable.gaosi1, R.drawable.gaosi2, R.drawable.gaosi}; private int index = 0;
 

 

 

 

Handler handler = new Handler();
 Runnable runnable = new Runnable() {
 @Override
 public void run() { 
index++;
 index = index % 3;
 imageView.setImageResource(images[index]); handler.postDelayed(runnable, 1000); 
}
 };
 

 

 最好别忘了post()一下。

handler.post(runnable);

这样就有三张南华大学的图片在不停的切换  在测试时候遇到了一点小插曲:图片使用*.png会出现找不到符号,可能是应为Android studio 1.3的bug缘顾吧,还有就是ImageView需拖进去,自己写的会显示不出图片。 Handler 与runnable搭配使用时候,最后别忘了removeCallbacks() 不然即使你的应用退出了,Handler还在继续,就像一个未被销毁的服务一样存在。 Handler发送消息: Handler不仅具有修改UI,post(),还发消息。

 

Handler handler1 = new Handler(){
 @Override 
public void handleMessage(Message msg) {
 super.handleMessage(msg);
 Log.e("msg.arg1",msg.arg1+"");
 }
 };
 

 

 

 
Message message = new Message();
 message.arg1 = 15;
 handler1.sendMessage(message);
 

 

 结果毫无疑问的打印出E/msg.ar1﹕ 15 细心的伙伴都会发现arg1、arg2都是int ,我如果要发的消息是其他类型或者是一个自定的对象呢? 发送的消息是好几个数据呢?那咋补? 放心,在message中有一参数 msg.obj;这个是可以传递一个Object的参数,问题解决也就那么简单。 还有一个方法message.setData(bundle);可以再bundle中封装多个数据多种类型都可。

 

Message message = handler1.obtainMessage();
 message.sendToTarget();
 

 

  消息也可以这样子发送,这一意思是将消息发送到目的Handler,使用这方法发送时的注意,message必须是目的Handler获取得到的,如果是new Message()会抛出一个空指针异常,原因就是没有目的Handler。 查看过谷歌官方提供的API会发现,Handler有几种构造方法,  看下第二种构造方法有啥作用?

 

Handler handler1 = new Handler(new Handler.Callback() {
 @Override 
public boolean handleMessage(Message msg) { Log.e("Callback_msg.arg1",msg.arg1+"");
 return false;
 } }
){
 @Override
 public void handleMessage(Message msg) {
 super.handleMessage(msg); 
Log.e("Handler_msg.arg1",msg.arg1+"");
 } 
};
 

 

 Callback里面重写的handleMessage()返回值为false与true又有啥区别? 当放回值为true时候,它会拦截msg的信息,为false时候不拦截。 返回值为true时候的结果

 返回值为false时候的结果

Looper:一种线程的消息循环  谷歌官方API提供的实现方法

 

class LooperThread extends Thread { 
public Handler mHandler; 
public void run() {
 Looper.prepare();
 mHandler = new Handler() {
 public void handleMessage(Message msg) {
 // process incoming messages here
 Log.e("threadID", Thread.currentThread().getId() + ""); 
} 
};
 Looper.loop(); 
} 
}
 

 

 handler必须在Looper.loop()之前,Looper.prepare()之后 只要调用下面的代码就可以运行起来了

threadLooper = new ThreadLooper(); threadLooper.start(); threadLooper.handler.sendEmptyMessage(1);

   使用就是这么简单,但是呢,运行上面的代码并不能成功,为啥?在发送消息之前还得让线程休眠一下,缓冲一下。不然会抛空指针异常的。这就是在多线程下,UI线程执行到下一行时候handler还没创建成功。怎么解决这种多线程导致的空指针异常呢?一,使用线程锁,二,HandlerTHread代替。 HandlerThread handlerThread到底是啥?Handy class for starting a new thread that has a looper. The looper can then be used to create handler classes. Note that start() must still be called handlerThread的使用:

 

HandlerThread handlerThread = new HandlerThread("handlerThread"); handlerThread.start();
 Log.e("currentThread_UI", Thread.currentThread().toString()); 
Handler handler = new Handler(handlerThread.getLooper()) {
 @Override
 public void handleMessage(Message msg) { 
super.handleMessage(msg); 
Log.e("currentThread_Handler", Thread.currentThread().toString());
 } 
}; 
handler.sendEmptyMessage(1);
 

 

  HandlerThread怎么来防止上面引发的空指针呢? 查看源代码也不能看出

 

  细心的人会注意到前面提到过,Handler+Runnable时候,他俩使用的是同时UI线程,在这里会不会也是一样呢?看运行的国果吧。

 Android为我们封装了HandlerThread,不仅是我们更好的预防Looper+Handler引发的空指针异常,还能成为独立于UI线程的子线程,在HandlerThread中我们可以操作耗时操作:请求网络等等。 更新UI的几种方法:

handler post;

handler sendmessage ;

runOnUiThread;

view post

怎么实现呢?前两种方法前面有所提及不再做详细的介绍 第三种方法:

runOnUiThread(new Runnable() { 
@Override
 public void run() {
 textView3.setText("gaosi");
 }
 }
);

 

  第四种方法:

textView4.post(new Runnable() { 
@Override 
public void run() {
 textView4.setText("gaosi");
 } });

 

   同时调用四种方法,几个用时改变UI,(上面是使用这四种方法同时改变textView1--4) 一定得要在UI线程才能更改UI吗?

new Thread(){ 
@Override 
public void run() {
 textView.setText("gaosi");
 try {
 sleep(2000); 
} catch (InterruptedException e) {
 e.printStackTrace(); 
} } }.start();

 

 这样的代码UI也能更新成功!!!你是否已经惊呆了?大多数的人都这样认为,更新UI都要在UI线程,但是这个例子是否让你的世界观瞬间巨变了呢?如果在更新UI前线sleep(),结果又会怎么怎么样子呢?这下可以让你找回一点自信了,抛出异常信息了!想要知道让你的世界观瞬间巨变的原因吗?欲知结果,请看Android源码。

  • 大小: 28.1 KB
  • 大小: 31.8 KB
  • 大小: 7.3 KB
  • 大小: 8.9 KB
  • 大小: 20.2 KB
  • 大小: 22.6 KB
  • 大小: 24.5 KB
  • 大小: 19.9 KB
  • 大小: 18.5 KB
分享到:
评论

相关推荐

    Android:Handler学习实例2(HandlerThread、Bundle传递参数)

    HandlerThread handlerThread = new HandlerThread("handler_thread"); //在使用HandlerThread的getLooper()方法之前,必须先调用该类的start()方法,否则获得的值为空值; handlerThread.start(); //创建...

    android HandlerThread 实例

    在Android开发中,`HandlerThread` 是一个非常重要的组件,特别是在处理异步任务和线程通信方面。`HandlerThread` 是一个内置了Looper的线程,它可以为长时间运行的任务提供一个独立的消息处理循环,避免阻塞主线程...

    了解Android核心:Looper,Handler和HandlerThread

    下面通过两个例子进一步说明如何使用Handler和HandlerThread: 1. 使用Thread创建主线程Handler: 在这个例子中,我们创建了一个新的Thread,并在其中创建了一个新的Handler实例(handler2)。然后,我们通过...

    Looper、Handler与HandlerThread

    在Android开发中,Looper、Handler和HandlerThread是三个非常重要的组件,它们构成了Android消息处理机制的基础,用于在主线程中处理来自其他线程的消息。理解并熟练运用这三个组件,对于编写高效、响应迅速的...

    Android HandlerThread 全面解析

    `HandlerThread`是Android中的一个内置类,它继承自`Thread`,并添加了`Looper`和`Handler`的支持。通常,当我们需要创建一个新的工作线程来处理耗时任务时,需要手动初始化`Looper`和`Handler`,而`HandlerThread`...

    Android:Handler的post()方法和Thread的start()方法执行Thread的run()方法的区别

    import android.os.Handler; import android.app.Activity; import android.view.Menu; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { ...

    HandlerThread

    【HandlerThread】是一种在Android系统中专为处理后台任务而设计的线程类。它继承自`Thread`,并结合了`Looper`和`Handler`的概念,使得开发者可以在子线程中创建一个消息循环,方便地处理来自主线程或其他线程的...

    handlerthread学习demo

    在Android开发中,`HandlerThread` 是一个非常重要的组件,特别是在处理异步任务和线程同步方面。`HandlerThread` 是一个内置了消息队列和Looper的线程,它的主要作用是提供一个稳定的、可控制的后台执行环境,用于...

    android HandlerThread 使用demo

    在Android开发中,`HandlerThread` 是一个非常重要的线程管理工具,它结合了线程和消息处理机制,常用于创建后台线程处理耗时任务,以避免阻塞主线程,提升用户体验。本示例("android HandlerThread 使用demo")将...

    【Android开发入门】Android线程之Handler

    3. 使用HandlerThread:当需要长时间运行的任务时,创建一个HandlerThread,它内置了Looper,方便在子线程中处理消息。 总结,Handler机制是Android开发中的重要知识点,它解决了在多线程环境中更新UI的问题,通过...

    HandlerThread的使用与自定义HandlerThread

    在Android开发中,`HandlerThread` 是一个非常重要的组件,尤其在处理异步任务和线程间通信时。本文将深入探讨 `HandlerThread` 的使用、工作原理,并讲解如何自定义 `HandlerThread`,以及为什么在某些场景下我们...

    HandlerThread使用demo

    HandlerThread在Android开发中是一种特殊的线程类,主要用于处理与UI线程同步的异步任务。它是基于Thread的,但提供了MessageQueue和Looper的集成,使得我们能够在子线程中方便地通过Handler来发送和处理消息。理解...

    Android handler message奇怪用法详解

    Handler是Android中的一个类,它用于在不同的线程之间发送和处理消息。通常,我们使用Handler配合Looper和Message来实现在主线程(UI线程)中执行后台任务的结果。Looper是消息队列的循环器,它不断检查消息队列并...

    android学习--handler

    标题“android学习--handler”暗示我们将探讨`Handler`在Android开发中的应用和原理。在Android系统中,主线程(UI线程)负责处理用户交互,而后台线程则执行耗时操作,如网络请求、数据处理等。`Handler`就是连接这...

    android-Handler的使用

    【Android Handler 使用详解】 Handler 是 Android 平台中用于处理线程间通信的关键组件,尤其在涉及 UI(用户界面)更新时,它扮演着至关重要的角色。在 Android 应用程序启动时,系统会默认创建一个主线程,也...

    Thread、Handler和HandlerThread关系详解

    ,这个题目有点意思,对于很多人来说,可能对Thread和Handler很熟悉,主要涉及到Android的消息机制(Handler、Message、Looper、MessageQueue),详见《 从Handler.post(Runnable r)再一次梳理Android的消息机制(以及...

    Android开发工程师面试题之handler详解。android程序员,android开发面试资料,详解

    - `HandlerThread`是Android提供的一种特殊线程,内部集成了Looper和Handler。 - 可以通过创建`HandlerThread`实例并启动线程,然后在该线程中使用Handler进行线程间的通信。 2. **Handler与AsyncTask的对比**: ...

    android多线程handler/message机制详解

    import android.os.HandlerThread; import android.os.Looper; import android.os.Message; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget...

    android 中Handler 的几种写法

    在Android开发中,`Handler`是一个至关重要的组件,它用于在主线程中处理来自其他线程的消息,确保UI更新和事件处理的同步性。本文将详细介绍`Handler`的几种常见写法,以及如何使用`Handler.Callback`进行消息处理...

    HandlerThread,AsyncTask,Handler的一个小例子

    总的来说,HandlerThread、AsyncTask和Handler都是Android中用于异步处理和UI更新的重要工具。理解并熟练掌握它们的使用,能帮助开发者编写出更加流畅、高效的Android应用。在实际项目中,应根据任务的性质和需求...

Global site tag (gtag.js) - Google Analytics