热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

数据同步异步加载handlerLooper

MainActivityimportandroid.app.Activity;importandroid.os.Bundle;importandroid.os.Handler;im

MainActivity

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;

/**
* 当点击按钮的时候,由子线程向主线程传递数据
*
* @author Administrator
*
*/
public class MainActivity extends Activity {
private Handler handler = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}

// 点击按钮,创建子线程
public void click_start(View v) {
new MyThread().start();
}

// 点击该按钮,数据从主线程传递到子线程中
public void click_send(View v) {
// 由handler发送数据
Message msg = Message.obtain();//
msg.what = 1;
msg.arg1 = 100;
msg.obj = "我是从主线程中传递来的数据";
handler.sendMessage(msg);// msg:target:handler
}

// 自定义类,继承Thread,表示用于子线程
class MyThread extends Thread {
@Override
public void run() {
// 子线程中要执行的代码:
// 用于接收主线程传来的数据
// 由handler接收处理数据就可以。
/**
* 报错信息: java.lang.RuntimeException: Can't create handler inside
* thread that has not called Looper.prepare()
*/
// 应该先执行:Looper.prepare();
/**
* 表示将当前的线程升级为:Looper线程
*
* 1.创建一个Looper对象。注意:一个线程中只能有一个Looper对象。用ThreadLocal
*
* 2.一个Looper对象,负责维护一个消息队列:new MessageQueue
*/
Looper.prepare();// 将子线程升级,成Looper线程。就可以操作handler对象。否则一个普通的子线程,不能操作handler。
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
int num = msg.arg1;
String str = (String) msg.obj;
Log.i("tag", "===子线程:" + Thread.currentThread().getId()
+ ",线程名字:" + Thread.currentThread().getName()
+ ",数据:" + num + ",str:" + str);
break;

default:
break;
}
}
};
Looper.loop();// 用于循环处理消息。
}
}

}

 

 

源码分析:

class MyThread extends Thread {
@Override
public void run() {
// 子线程中要执行的代码:
// 用于接收主线程传来的数据
// 由handler接收处理数据就可以。
/**
* 报错信息: java.lang.RuntimeException: Can't create handler inside
* thread that has not called Looper.prepare()
*/
// 应该先执行:Looper.prepare();
/**
* 表示将当前的线程升级为:Looper线程
*
* 1.创建一个Looper对象。注意:一个线程中只能有一个Looper对象。用ThreadLocal
*
* 2.一个Looper对象,负责维护一个消息队列:new MessageQueue
*/
Looper.prepare();// 将子线程升级,成Looper线程。就可以操作handler对象。否则一个普通的子线程,不能操作handler。
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
int num = msg.arg1;
String str = (String) msg.obj;
Log.i("tag", "===子线程:" + Thread.currentThread().getId()
+ ",线程名字:" + Thread.currentThread().getName()
+ ",数据:" + num + ",str:" + str);
break;

default:
break;
}
}
};
Looper.loop();// 用于循环处理消息。
}
}



要想通过Hanlder对象来异步处理消息,必须要让handler所在的线程变为Looper线程。


一。Looper:循环器
public class Looper {
//ThreadLocal线程本地变量,用于为该线程中只有一个Looper对象。
static final ThreadLocal sThreadLocal = new ThreadLocal();
//Looper内部维护的消息队列
final MessageQueue mQueue;
//当前线程对象本身
final Thread mThread;


...
//用于初始化创建Looper
public static void prepare() {
prepare(true);
}
//创建Looper
private static void prepare(boolean quitAllowed) {
//从sThreadLocal线程本地变量中获取Looper。如果不为空,意味着已经有Looper对象了。
if (sThreadLocal.get() != null) {
//抛出异常
throw new RuntimeException("Only one Looper may be created per thread");
}
//创建一个Looper对象,并且存入sThreadLocal线程本地变量中获取Looper
sThreadLocal.set(new Looper(quitAllowed));
}

....
//Looper的构造方法
private Looper(boolean quitAllowed) {
//同时创建该Looper对象所维护的消息队列
mQueue = new MessageQueue(quitAllowed);
mRun = true;
mThread = Thread.currentThread();
}


...
//循环工作
public static void loop() {
//获取当前的looper对象
final Looper me = myLooper();
//获取消息队列
final MessageQueue queue = me.mQueue;
//循环处理消息
for (;;) {
Message msg = queue.next(); // 从消息队列中获取消息

msg.target.dispatchMessage(msg);//将msg交给对应的handler去分发。msg.target:就是对应的handler
//handler.dispatchMessage(msg);

msg.recycle();//回收消息到消息池,便于下次使用。
}

}
//从线程的本地变量中获取Looper对象
public static Looper myLooper() {
return sThreadLocal.get();
}
}




总结:Looper的注意事项
1.每一个线程只能有最多一个Looper对象。
2.当创建Looper的同时,MessageQueue一同被创建。
3.调用loop()方法,循环从消息队列上获取消息,分发给对应的handler。




-------------------------------------------------------
二。Handler:异步处理者,用于发送和处理消息的。

public class Handler {
//与当前的handler对象关联的消息队列
final MessageQueue mQueue;
//与handler关联的Looper对象

final Looper mLooper;

final Callback mCallback;

//创建Handler对象
public Handler() {
this(null, false);
}

public Handler(Callback callback, boolean async) {
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;//将Looper维护的消息队列,赋值给当前handler所关联的消息队列。
mCallback = callback;
}

..
//由handler发送消息到关联的消息队列上。
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}

public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis <0) {
delayMillis &#61; 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() &#43; delayMillis);
}

public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue &#61; mQueue;
if (queue &#61;&#61; null) {
RuntimeException e &#61; new RuntimeException(
this &#43; " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
//为当前的message贴标签&#xff1a;当前的handler对象
msg.target &#61; this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}


...
//分发消息:在Looper.loop()中调用。
public void dispatchMessage(Message msg) {
if (msg.callback !&#61; null) {
handleCallback(msg);
} else {
if (mCallback !&#61; null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}

}
//由接收数据的线程&#xff0c; 重写的方法&#xff0c;表示处理msg
public void handleMessage(Message msg) {
}

handler.post();
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
private static Message getPostMessage(Runnable r) {
Message m &#61; Message.obtain();
m.callback &#61; r;//重写的new Runnalbe(){public void run(){}}
return m;
}

private static void handleCallback(Message message) {
message.callback.run();//执行自己重写new Runnalbe(){public void run(){}}
}
}


Handler的属性和方法&#xff1a;
属性&#xff1a;
final MessageQueue mQueue;
final Looper mLooper;
final Callback mCallback;


方法&#xff1a;5个重要方法
sendMessage(msg);
handleMessage();
post();
sendEmptyMessage();
obtainMessage();


dispatchMessage();
sendMessageDelayed();
sendMessageAtTime();


Handler的总结&#xff1a;
注意事项&#xff1a;
1.当创建Handler对象的时候&#xff0c;(应该先有Looper)。那么handler对象会和Looper相关联&#xff0c;以及和消息队列相关联。
2.handler发送消息到消息队列&#xff0c;其实就是发送到关联的消息队列中。该消息队列是由对应的Looper维护。


三。Message

public final class Message implements Parcelable {
public int what;
public int arg1;
public int arg2;
public Object obj;
}
what
arg1
arg2
obj
方法&#xff1a;
obtain();
setTarget(Handler target)
setData()
sendToTarget();

总结&#xff1a;
1.每一个线程最多只能有一个Looper
2.一个looper负责维护一个MessageQueue
3.Handler必须在Looper所在的线程创建。

 

转:https://www.cnblogs.com/achen0502/p/5098141.html



推荐阅读
  • 深入理解设计模式之观察者模式
    本文详细介绍了观察者模式,这是一种行为设计模式,适用于当对象状态发生变化时,需要通知其他相关对象的场景。文中不仅解释了观察者模式的基本概念,还通过Java代码示例展示了其实现方法。 ... [详细]
  • 本文将详细介绍NSRunLoop的工作原理,包括其基本概念、消息类型(事件源)、运行模式、生命周期管理以及嵌套运行等关键知识点,帮助开发者更好地理解和应用这一重要技术。 ... [详细]
  • 详解 | 日志系统ViseLog的基本使用与功能
    本文详细介绍了日志系统ViseLog的使用方法及其核心功能,旨在帮助开发者更好地理解和利用这一工具,提高开发效率。 ... [详细]
  • 本文详细介绍了Java中RulesBasedCollator类的getCollationElementIterator(String source)方法,包括其功能、使用场景及代码示例。 ... [详细]
  • Java Servlet中获取客户端IP与MAC地址的方法
    本文介绍了一种在Java Servlet应用中获取客户端IP地址及MAC地址的技术实现方法,通过示例代码详细解析了获取过程中的关键步骤和技术点。 ... [详细]
  • Java EE CDI:解决依赖关系冲突的实例
    在本教程中,我们将探讨如何在Java EE的CDI(上下文和依赖注入)框架中有效解决依赖关系的冲突问题。通过学习如何使用限定符,您将能够为应用程序的不同客户端提供多种接口实现,并确保每个客户端都能正确调用其所需的实现。 ... [详细]
  • 本文将探讨从ASP.NET 1.1到2.0期间编译系统的重要变革。通过对比两个版本的即时编译模型,我们将揭示2.0版本中引入的新特性和改进之处。 ... [详细]
  • 本文深入探讨了Java中的代理模式,包括静态代理和动态代理的概念、实现及其应用场景。通过具体的代码示例,详细解析了如何利用代理模式增强代码的功能性和灵活性。 ... [详细]
  • 利用RabbitMQ实现高效延迟任务处理
    本文详细探讨了如何利用RabbitMQ实现延迟任务,包括其应用场景、实现原理、系统设计以及具体的Spring Boot实现方式。 ... [详细]
  • 本文介绍了如何通过扩展 Panel 控件来实现滚动条位置的自动保存和恢复。类似于 Page 的 MaintainScrollPositionOnPostBack 属性,我们将在自定义的 TBPanel 控件中添加相同的功能。 ... [详细]
  • 单例模式是软件开发中常用的设计模式之一,用于确保一个类只有一个实例,并提供一个全局访问点。本文探讨了在单例模式实现中使用volatile关键字的重要性,特别是在懒汉模式下的应用。 ... [详细]
  • 深入理解Java MySQL数据库连接池实现
    尽管利用Apache Commons DBCP等工具可以轻松构建数据库连接池,但本文详细解析了数据库连接池的工作机制,提供了详尽的注释,帮助开发者深入理解其内部运作。这不仅有助于提高数据库操作的效率,还能增强应用程序的稳定性和性能。 ... [详细]
  • 深入理解Quartz:Java定时任务框架详解
    Quartz是一个功能强大的调度库,适用于各种规模的应用程序。本文将详细介绍Quartz的基本概念、配置方法以及如何在Java项目中使用Quartz来管理定时任务。 ... [详细]
  • 本文详细介绍了如何在Mac操作系统中利用Java编程语言执行Android Debug Bridge (ADB) 的'devices'命令,以获取连接到系统的Android设备列表。 ... [详细]
  • 本文详细介绍了 Activiti 引擎中的 JobQuery.withException 方法,并提供了多个实际应用的代码示例,帮助开发者更好地理解和使用该方法。 ... [详细]
author-avatar
菜蔸蔸
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有