之前的例子都是我们在子线程(WorkerThread)当中处理并发送消息,然后在主线程(UI线程)中获取消息并修改UI,那么可以不可以在由主线程发送消息,子线程接收呢?我们按照之前的思路写一下代码:

package cn.lixyz.handlertest;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button; public class MainActivity extends Activity { private Button button;
private Handler handler;
private int i = 0; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); button = (Button) findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("TTTT", "onClick:" + Thread.currentThread().getName());
Message msg = handler.obtainMessage();
handler.sendMessage(msg);
}
}); WorkerThread wt = new WorkerThread();
wt.start();
} class WorkerThread extends Thread {
@Override
public void run() {
super.run();
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.d("TTTT", "收到了消息对象");
}
};
}
}
}

MainActivity.java

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity"> <Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="30dp"
android:text="Send Message" /> </LinearLayout>

activity_main.xml

上面的问题貌似没什么错误,但运行时却出错

抛出异常:

09-17 04:01:31.655  15854-15869/? E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-120
Process: cn.lixyz.handlertest, PID: 15854
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:200)
at android.os.Handler.<init>(Handler.java:114)
at cn.lixyz.handlertest.MainActivity$WorkerThread$1.<init>(MainActivity.java:48)
at cn.lixyz.handlertest.MainActivity$WorkerThread.run(MainActivity.java:48)

  

提示我们没有调用Looper.prepare(),无法创建线程,原因是非主线程中默认是没有创建Looper对象的,需要先调用Looper.prepare()启用Looper。修改一下上面的代码。

package cn.lixyz.handlertest;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button; public class MainActivity extends Activity { private Button button;
private Handler handler; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); button = (Button) findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Message msg = handler.obtainMessage();
msg.what = 100;
handler.sendMessage(msg);
Log.d("TTTT", "sendMessage:" + Thread.currentThread().getName());
}
}); WorkerThread wt = new WorkerThread();
wt.start();
} class WorkerThread extends Thread {
@Override
public void run() {
super.run();
Looper.prepare();
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.d("TTTT", "handleMessage:" + Thread.currentThread().getName());
int i = msg.what;
Log.d("TTTT", "收到了消息对象:" + i);
}
};
Looper.loop();
}
}
}

MainActivity.java

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity"> <Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="30dp"
android:text="Send Message" /> </LinearLayout>

activity_main.xml

运行结果:

09-17 04:29:48.669  28397-28397/cn.lixyz.handlertest D/TTTT﹕ sendMessage:main
09-17 04:29:48.669 28397-28410/cn.lixyz.handlertest D/TTTT﹕ handleMessage:Thread-141
09-17 04:29:48.669 28397-28410/cn.lixyz.handlertest D/TTTT﹕ 收到了消息对象:100

上面代码表示,消息是从MainThread发送的,WorkerThread接收到了消息。

 PS:非UI线程默认是没有创建Looper对象的,所以需要主线程向子线程传递消息时,需创建Looper对象并启动循环,子线程才可以循环着从MaessageQueue中取出消息。  

Android笔记(三十二) Android中线程之间的通信(四)主线程给子线程发送消息的更多相关文章

  1. Java 并发编程中的 CountDownLatch 锁用于多个线程同时开始运行或主线程等待子线程结束

    Java 5 开始引入的 Concurrent 并发软件包里面的 CountDownLatch 其实可以把它看作一个计数器,只不过这个计数器的操作是原子操作,同时只能有一个线程去操作这个计数器,也就是 ...

  2. Android 使用handler实现线程间发送消息 (主线程 与 子线程之间)、(子线程 与 子线程之间)

    keyword:Android 使用handler实现线程间发送消息 (主线程 与 子线程之间).(子线程 与 子线程之间) 相信大家平时都有使用到异步线程往主线程(UI线程)发送消息的情况. 本文主 ...

  3. Android线程之主线程向子线程发送消息

    和大家一起探讨Android线程已经有些日子了,谈的最多的就是如何把子线程中的数据发送给主线程进行处理,进行UI界面的更新,为什么要这样,请查阅之前的随笔.本篇我们就来讨论一下关于主线程向子线程如何发 ...

  4. Handler详解系列(四)——利用Handler在主线程与子线程之间互发消息,handler详解

    MainActivity如下: package cc.c; import android.app.Activity; import android.os.Bundle; import android. ...

  5. Handler具体解释系列(四)——利用Handler在主线程与子线程之间互发消息

    MainActivity例如以下: package cc.c; import android.app.Activity; import android.os.Bundle; import androi ...

  6. JAVA进阶----主线程等待子线程各种方案比较(转)

    创建线程以及管理线程池基本理解 参考原文链接:http://www.oschina.net/question/12_11255?sort=time 一.创建一个简单的java线程 在 Java 语言中 ...

  7. 在C#主线程和子线程将数据传递给对方如何实现

    在C#中主线程和子线程怎样实现互相传递数据 老帅 在C#中创建线程Thread时,能够有多种方法,而主线程和子线程之间又怎样实现互相传递数据,每种创建方法传递參数的效果是不同的,逐一看一下:  一.不 ...

  8. [C#参考]主线程和子线程之间的参数传递

    几个进程在大多数情况下要包含很多的子线程,那么他们之间免不了的要互相传递很多的参数,那么参数怎么传递的呢? 主线程向子线程传递参数的方法 第一种方法:Thraed类有一个带参数的委托类型的重载形式,这 ...

  9. Python_线程、线程效率测试、数据隔离测试、主线程和子线程

    0.进程中的概念 三状态:就绪.运行.阻塞 就绪(Ready):当进程已分配到除CPU以外的所有必要资源,只要获得处理机便可立即执行,这时的进程状态成为就绪状态. 执行/运行(Running)状态:当 ...

随机推荐

  1. F5 BIG-IP – Useful SNMP oids to monitor

    I have collected some of the most interesting OIDs (in my scenario im using LTM and APM modules) fro ...

  2. C#中,子线程与主线程之间的通信是如何实现(转)

    注: 项目中按照这个方法调试成功: 通常我们会有这种需求: 一个支持慢速设备的处理类,如网络通信.串口通信.打印等 此时经常需要将线程封装在类里面,让类支持异步处理,然后发布事件或者回调委托通知主线程 ...

  3. 解决javascript - node and Error: EMFILE, too many open files

    For some days I have searched for a working solution to an error Error: EMFILE, too many open files ...

  4. linux如何查看mysql是否启动

    linux下有很多服务,今天就写一下如何查看服务是否启动,以mysql为例子 使用命令 # service mysqld status 或者 # service mysql status 命令来查看m ...

  5. 【GStreamer开发】GStreamer基础教程14——常用的element

    目标 本教程给出了一系列开发中常用的element.它们包括大杂烩般的eleemnt(比如playbin2)以及一些调试时很有用的element. 简单来说,下面用gst-launch这个工具给出一个 ...

  6. WCF之Windows宿主(可安装成服务自动并启动)

    WCF之Windows宿主(可安装成服务自动并启动) 创建解决方案WCFServiceDemo 创建WCF服务库(类库或WCF服务库)WCFService  ,添加引用System.ServiceMo ...

  7. jira7.3.6 linux安装及破解

    一.环境准备 jira7.3的运行是依赖java环境的,也就是说需要安装jdk并且要是1.8以上版本,如下: http://www.oracle.com/technetwork/java/javase ...

  8. composer安装扩展包异常

    我是tp5.1下,用composer安装扩展包,在命令行运行,无任何不反应,不下载也不报错,这时,我们先ctrl+c退出执行的命令,然后在tp5.1根目录下,找到composer.json文件,并用编 ...

  9. [学习笔记] 下载、安装、启动 Eclipse(OEPE)

    OEPE 的全称是: Oracle Enterprise Pack for Eclipse 截止目前的最新版本是:(12.2.1.9) 下载地址:(需要在甲骨文官网注册一个账户才能下载) https: ...

  10. 013 Android 实现流水灯功能+自定义控件的样式(可以复用)

    1.介绍 (1)获取屏幕的焦点 android:focusable与android:focusableInTouchMode(获取屏幕焦点) 前者针对在键盘下操作的情况,如果设置为true,则键盘上下 ...