- 浏览: 189324 次
- 性别:
- 来自: 郑州
最新评论
-
gaoyansansheng:
,第一个方法是全角符转半角符吧?
Android TextView自动换行文字排版参差不齐的原因 -
wyyl1:
牛逼!用第一个方法就行了,简单!
Android TextView自动换行文字排版参差不齐的原因 -
XuNiu:
好内容虽然过了这么久了,但是一定要赞一下
android 命名规范
Android多线程
作者:陈正
最本质的多线程:hanlder和message机制:
为何需要多线程:
在日常应用中,我们通常需要处理一些“后台,用户不可见”的操作,例如说,我们需要下载一个音乐,要是你的应用必须等用户下载完成之后才可以进行别的操作,那肯定让用户非常的不爽。这时候,我们通常的做法是,让这些操作去后台执行,然后等后台执行完毕之后,再给用户弹出相应的提示信息。这时候,我们就需要使用多线程机制,然后通过创建一个新的线程来执行这些操作。
明白了,实现需求,我们就准备着手实现了。但是,经过进一步的了解,我们悲剧的发现,android中的线程机制是,只能在UI线程中和用户进行交互。当我们创建了一个新线程,执行了一些后台操作,执行完成之后,我们想要给用户弹出对话框以确认,但是却悲剧的发现,我们根本无法返回UI主线程了。
(说明:何为UI线程:UI线程就是你当前看到的这些交互界面所属的线程)。
这时候,我们如果想要实现这些功能,我们就需要一个android为我们提供的handler和message机制。
先讲解下编程机制:
我们通常在UI线程中创建一个handler,handler相当于一个处理器,它主要负责处理和绑定到该handler的线程中的message。每一个handler都必须关联一个looper,并且两者是一一对应的,注意,这点很重要哦!此外,looper负责从其内部的messageQueue中拿出一个个的message给handler进行处理。因为我们这里handler是在UI线程中实现的,所以经过这么一个handler、message机制,我们就可以回到UI线程中了。
何为handler:处理后台进程返回数据的工作人员。
何为message:后台进程返回的数据,里面可以存储bundle等数据格式
何为messageQueue:是线程对应looper的一部分,负责存储从后台进程中抛回的和当前handler绑定的message,是一个队列。
何为looper:looper相当于一个messageQueue的管理人员,它会不停的循环的遍历队列,然后将符合条件的message一个个的拿出来交给handler进行处理。
注意,handler是在UI线程中声明的,如果我们直接用类似代码执行一个线程的话,实际上并没有创建一个新的线程,因为handler已经跟默认的UI线程中的looper绑定了。
private void test(){ MyHandler handler = new MyHandler(); handler.post(new Runnable(){ @override public void run(){ System.out.println("hello baby"); } } ); }
如果有兴趣的话,可以去看下Handler的默认空构造函数便知道愿意了,里面直接绑定了当前UI线程的looper。
下面给出一个比较简单,并且实用的实例。
package cn.com.src; import cn.com.chenzheng_java.utils.R; import android.app.Activity; import android.os.Bundle; import android.os.Handler; 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.Button; /** * @author chenzheng_java * handler和message测试用例 */ public class HanlderMessageTest extends Activity implements OnClickListener{ Button button ; MyHandler handler ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); button = (Button) this.findViewById(R.id.button1); button.setOnClickListener(this); } // 声明自己的handler private class MyHandler extends Handler{ /** * 使用默认的构造函数,会将handler绑定当前UI线程的looper。 * 如果想使用多线程这里是不能使用默认的构造方法的。 */ public MyHandler() { super(); } public MyHandler(Looper looper){ super(looper); } // 处理具体的message,该方法由父类中进行继承. @Override public void handleMessage(Message msg) { int whatNumber = msg.what; Bundle bundle = (Bundle)msg.obj; Log.i("what", whatNumber+""); Log.i("名称", bundle.getString("name")); Log.i("性别", bundle.getString("sex")); Log.i("年龄", bundle.getString("age")); super.handleMessage(msg); } } // 我自定义的任务,一般都会实现Runnable private class MyThread implements Runnable { /** * 该方法的内部进行具体的任务实现,比如 下载. * Message中包含着想和ui线程交互的数据,原则上,在线程内部是 * 最好不要直接调用handler的。 * */ @Override public void run() { try { Thread.sleep(6000); Message message = Message.obtain(handler); message.what = 10 ; Bundle bundle = new Bundle(); bundle.putString("name", "chenzheng"); bundle.putString("sex", "纯爷们"); bundle.putString("age", "生卒年不详"); message.obj = bundle ; Log.i("通知", "开始发message了哦"); Log.i("通知thread_id:", ""+Thread.currentThread().getId()); message.sendToTarget(); } catch (Exception e) { Log.i("通知", "线程sleep时出错了!"); e.printStackTrace(); } } } @Override public void onClick(View v) { Log.i("通知thread_id:", ""+Thread.currentThread().getId()); // 创建一个包含Looper的线程,这里如果没有HandlerThread的调用,会直接将后边的MyThread放到UI线程队列 HandlerThread myHandlerThread = new HandlerThread("chenzheng_java"); // 启动新线程 myHandlerThread.start(); // 将handler绑定到新线程 handler = new MyHandler(myHandlerThread.getLooper()); // 在新线程中执行任务 handler.post(new MyThread()); } }
这里,很多人不理解,HandlerThread到底是干什么的?
HandlerThread实际上继承自Thread,属于Thread的加强版。在其内部添加了和该Thread相绑定的loop,
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper()
notify();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
从代码中可以看出主要的区别就在于调用了Looper.prepare()、Looper.loop()以启用和开始消息队列。我们自己也可以继承Thread并模仿HandlerThread做一个线程类用于启动新的线程。 Message.sendToTarger()请不要用handler.sendMessage()等方法跑出,因为这样message会将target直接绑定到调用的handler上,还是那句老话,不建议在任务内部出现对handler的直接调用。当然,如果你一定要那么做,我只能说,OK,没问题的。 读到这里,如果你还不明白handler和looper是一一对应的,那你只能倒回去再看几遍了。 源码的一些理解: Handler:handler最主要的用途还是对消息进行分发和处理,所以我们在提供handler的时候,是被严格要求继承重写handlerMessage方法的。它是很被动的。 Message:可以简单的认为是一个Object对象。只不过有些特殊而已,因为它有一个what属性来与其他message进行区分。可以通过Message message = Message.obtain(handler);或者Message message = Message.obtain();message.setTarget这两种方式指定message的handler。记住,此处一定要显示的指定handler,否则程序会报出空指针异常哦。 MessageQueue:其内部是通过一个ArrayList来实现的,并不是简单的先进先出哦,而是有优先级的。如果我们不对线程优先级进行设计,默认的是先进先出,但是如果我们显示的设置了线程的优先级,是会起作用的哦。 Looper:上面我们说handler是被动的,为什么呢,原因就是looper的存在。Looper的实现就类似一个while(true)的循环一样,然后从里面读取数据,如果读到存在message,就将其传递给相应的handler进行处理。 其他,在android还提供了一些其他的帮助类: AsyncTask:其内部实现机制就是handler和message机制。通过它可以方便的实现启动一个线程去后台执行复杂操作的需求。 AsyncQueryHandler实际上继承自Handler,它并不和handler一样属于android.os包中,它属于android.content包中,仅仅凭此,我们就知道,这是为了给content内部的应用进行定制的类。实际上,也确实如此,该类是专门为内容提供者提供异步执行的类,该类在哪一个线程中new的,该任务就会在当前线程中执行哦。如图
我们可以看到,除了必要的增删改查之外,还提供了一些在增删改查完成之后执行的相应方法,在这里实际上我们可以添加一些更新展示给用户的数据等操作。 一定要注意,该类直接就绑定了当前线程的looper,它也没有提供有Looper参数的构造方法,所以这点一定要注意。
发表评论
-
android textview 特出显示
2013-04-22 19:40 1637在xml文件中使用android:textStyle=&qu ... -
反编译apk
2013-02-27 10:42 975工具下载:需用到dex2ja ... -
Android 通过字符串来获取R下面资源的ID 值
2013-01-30 14:33 1201方法一: try{ Field field= ... -
android禁止锁屏保持常亮 .
2012-12-26 11:12 4716在播放video的时候在mediaplayer mMedia ... -
Eclipse开发Android的配置(包括ADT安装,SDK配置)
2012-12-08 12:35 18261. 下载Android SDK htt ... -
android 命名规范
2012-12-03 19:16 4147一、Android编码规范 1.java代码中不出现中文 ... -
div+css命名规范 嫁接android xml命名
2012-12-03 19:13 1092CSS命名规则 头:header 内容:co ... -
android 之 Task Activity .
2012-11-27 20:55 2594首先task包含一个或多个activity,它是安排在一个堆栈 ... -
android之多线程工作(一)AsyncTask .
2012-11-27 19:35 1329本文章主要讲解下AsyncTa ... -
Android 重要包描述
2012-10-25 13:21 973在Android中,各种包写成android.* 的方式,重要 ... -
android.os.NetworkOnMainThreadException 异常处理
2012-10-20 15:12 1088android.os.NetworkOnMainThreadE ... -
android textview属性
2012-08-24 16:10 849android:autoLink设置是否当 ... -
GestureDetector.OnDoubleTapListener 和 GestureDetector.OnGestureListener
2012-07-20 21:30 2000android.view.GestureDetector. ... -
Android Google Map API的使用(一)
2012-07-17 20:49 1101Android中定义了一个名为com.google.andro ... -
Android中Context简介
2012-07-15 19:20 10370Context字面意思是上下文,位于framework pac ... -
XmlPullParser
2012-07-06 16:14 10318在Android中,如果要想完成PULL解析处理需要 o ... -
DocumentBuilder API 官方翻译(翻译有错的地方请多指正)
2012-07-04 12:27 1255public abstract class Document ... -
Android开发如何去除标题栏title
2012-07-02 18:18 787Android开发如何去除标题栏title 去除标题栏tit ... -
Android 获取存储卡路径和空间使用情况
2012-07-01 16:55 5705/** 获取存储卡路径 */ File sdc ... -
Problems occurred when invoking code from plug-in: "org.eclipse.core.resources".
2012-06-30 17:25 7570今天在写一个小例子时,处了一个错误让我找了一下午,下面是错误代 ...
相关推荐
本实例关注的是如何在Android NDK环境下实现一个类似Java层的消息队列(Message Queue)和Handler机制,以及如何在原生代码中创建和管理多线程。 首先,我们要理解Java层的Handler和消息队列的工作原理。在Java中,...
总结来说,Android的线程消息传递机制是一种高效且安全的多线程通信方式,通过Handler、Message和Looper三者协同工作,实现了后台线程与主线程之间的数据交换。理解并熟练掌握这一机制,对于优化Android应用性能、...
Handler、Message和Looper三者协同工作,Handler发送消息,Looper循环处理消息,保证了数据在正确线程中被处理。 具体步骤如下: 1. 创建Handler实例,通常在主线程中。 2. 在工作线程中,通过Handler的sendMessage...
`Handler`是Android中的消息处理机制核心组件,它与`Looper`和`MessageQueue`一起工作,实现线程间通信。`Handler`主要用于发送和处理消息,通常在主线程中创建,这样可以确保UI更新在主线程中进行,避免出现ANR...
`Handler`、`Looper`和`Message`是Android异步消息处理机制的核心组成部分。下面将详细阐述`Handler`的工作原理以及如何在`Activity`中使用它。 `Handler`是Android提供的一个接口,通过它可以发送和处理Message或...
然而,由于其内部对线程的管理和限制,不建议在`AsyncTask`中执行长时间运行的操作,因为这可能会导致多个`AsyncTask`实例间的资源竞争问题。 - **Handler**则更适合于复杂的异步通信场景,特别是当需要在主线程和...
使用getMainLooper / **在Apache许可版本2.0(“许可”)下许可的hanlder进行测试; 除非遵守许可,否则您不得使用此文件。 您可以在以下位置获得许可证的副本: http://www.apache.org/licenses/LICENSE-2.0 ...
归纳总结: 1. 从缓存中读取图片:先从内存缓存中读取。 若是从内存中读取到的Bitmap为空,则在磁盘缓存中读取。 若是从磁盘中读取到的Bitmap为空,则从起始资源中读取 2....最后Hanlder更新UI
1.什么是handler? Handler是Android SDK来处理异步消息的核心类。...可以通过Handler将Message和Runnable对象发送到该Handler所关联线程的MessageQueue(消息队列)中,然后该消息队列一直在循环拿出一个Message,对其
我们在使用Handler的时候与Message打交道最多,Message是Hanlder机制向开发人员暴露出来的相关类,可以通过Message类完成大部分操作Handler的功能。但作为程序员,我不能只知道怎么用Handler,还要知道其内部如何...
可多开启无数个线程,当下载任务超过已设置的线程多余的任务会等待,当有下载完成时会自动唤起等待的任务,用了hanlder发送消息(可以改成广播的形势),可邮件跟我交流技术哦(wikeryong@qq.com)
上传和下载,分片资源,主要代码在拆分和组合,就是文件流的读取和写入!(我看了别人的代码,一大堆,这个最简洁了!) 可以作为断点上传和断点下载 Hanlder2.ashx表示从文件一个地方通过拆分流到另外一个地方,是...
RabbitMQ中的几种模式和机制比ActiveMQ多多了,根据业务需要,使用RPC实现功能,其中踩过的一些坑,有必要记录一下了。 上代码,目录结构分为 c_server、c_client、c_hanlder: c_server: #!/usr/bin/env python # ...
# Install pipxpython -m pip install pipx# Install pycontw-mail-hanlder through pipxpython -m pipx install pycontw-mail-handler 安装pycontw-mail-handler ,您可以在您的环境中运行render_mail和send_mail...
`AsyncTask`是Android提供的一种轻量级的异步处理机制,它简化了在UI线程和后台线程之间进行数据交互的过程。本示例“AsyncTask应用下载MP3”就是演示如何利用`AsyncTask`来实现MP3文件的下载,并通过进度条动态展示...
利用MainLooper每次调用dispatchMessage前后都会利用Printer打印日志,如果dispatchMessage执行超时则卡顿出现,只需记录dispatchMessage执行时间超过一定时间则记录相关信息
安装: go get github.com/ivahaev/amigo 使用将模块导入您的项目: import "github.com/ivahaev/amigo" 然后使用: package mainimport ("fmt""github.com/ivahaev/amigo")// Creating hanlder functionsfunc ...
将gdb.kak和gdb-output-hanlder.perl添加到您的自动加载目录中: ~/.config/kak/autoload/ ,或手动获取它。 这两个文件必须位于同一目录中,脚本才能工作。 您至少需要Kakoune v2019.01.20。 另外,此脚本对gdb ...
Android提供了几种在其他线程中访问UI线程的方法,如Activity.runOnUiThread( Runnable )、View.post( Runnable )、View.postDelayed( Runnable, long )、Hanlder等。这些类或方法同样会使你的代码很复杂很难理解。...
##SYSU-Course###依赖Python 2.7Tornado 3.0...其中里面的 modules 为 UI 模块###models数据库操作,包括 Course 类和 Comment 类###urls.pyurl 对应 Hanlder###server.py启动本地服务器###app.pyTornado 相关配置