【Android】Android实现Handler异步详解
方式不止一种,这里使用的是Timer类,创建一个定时器。我们经常需要获得移动设备端口的显示屏信息,但是onCreate()方法执行的时候,OnShow()方法不一定执行了,也就是说,在执行Oncreate()时候屏幕还没加载出来,所以这时候可以应用一个异步机制获取数据。
import android.app.Activity;
import android.os.Handler;
import android.os.Message;
import android.view.View; import java.util.Timer;
import java.util.TimerTask; /**
* Created by Lenovo on 2017/6/2.
*/
public abstract class MyActivity extends Activity{
protected abstract void ViewAfterShow(int width,int hight);
/**
* 使用线程异步,获取视图上的数据,比如高和宽
* @param viewID 视图ID
* @param msgID 消息ID
*/
protected void ViewShowListen(final int viewID,final int msgID){
//always make sure that schedule is running from main thread
if(Looper.getMainLooper() == Looper.myLooper())
runTimeSchedule(viewID,msgID);
else
new Handler(getMainLooper()).post(new Runnable() {
@Override
public void run() {
runTimeSchedule(viewID,msgID);
}
}); }
public void runTimeSchedule(final int viewID,final int msgID){
final int f_viewID = viewID;
final int f_msgID = msgID;
final Timer f_timer = new Timer();
final Handler f_handler = new Handler(){
@Override
public void handleMessage(Message msg){
if(msg.what == f_msgID){
View v = (View)findViewById(f_viewID);
if(v.getWidth() != 0 && v.getHeight() != 0){
f_timer.cancel();//取消
ViewAfterShow(v.getWidth(),v.getHeight());//回调信息
}
}
}
};
//这里之所以不在该run()方法里进行操作,是因为里面的数据是最终的,所以这里应用了一个消息发送机制。
TimerTask task = new TimerTask() {
@Override
public void run() {
Message message = new Message();
message.what = f_msgID;
f_handler.sendMessage(message);//发送消息
}
};
//延迟每次延迟10毫秒 隔500毫秒执行一次
f_timer.schedule(task,10,500);
}
}
上面是关于TimerTask和Handler的一种用法,上面调用的是Handler的 sendMessage(Message msg) ,除了sendMessage方法,还有 handleMessage(Message msg) 方法,注意handleMessage方法和sendMessage方法的效果是不一样的,sendMessage是handler在主线程中执行;但是handlerMessage则不会,所处理的Handler还是在Timer线程中。
下面详细介绍一下TimerTask类和Handler类,TimerTask中创建的线程是一个单独的线程,命名通常以 timer+数字 表示,一帮数字从0开始。而Hanler不会创建新的线程,如果不使用Looper标识,那么Handler处于的线程将会是在main(主)线程中,比如:
public class MainActivity extends Activity {
Context context;
LinearLayout layout;
int f_msgID = 2;
final Timer f_timer = new Timer();
final Handler f_handler = new Handler(){
@Override
public void handleMessage(Message msg){
if(msg.what == f_msgID){
Log.e("d", Thread.currentThread().getName());//main
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context=this;
layout=(LinearLayout)findViewById(R.id.mainlayout);
Log.e("a",Thread.currentThread().getName());//main
new Thread(new Runnable() {
@Override
public void run() {
Log.e("b", Thread.currentThread().getName());//thread-11840
TimerTask task = new TimerTask() {
@Override
public void run() {
Message message = new Message();
message.what = f_msgID;
f_handler.sendMessage(message);
Log.e("c", Thread.currentThread().getName());//timer-0
}
};
f_timer.schedule(task,10,10000);
}
}).start();
}
}
笔者在上面的代码上中,标识出了各个线程中运行的线程名称,一共有三个线程,可以发现Handler所处的线程是在主线程中的。
接下来如果是使用Looper的话,Handler所处的线程为Looper所处的线程,比如:
public class MainActivity extends Activity {
Context context;
LinearLayout layout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = this;
layout = (LinearLayout) findViewById(R.id.mainlayout);
Log.e("a", Thread.currentThread().getName());// main
new Thread(new Runnable() {
@Override
public void run() {
Log.e("b", Thread.currentThread().getName());// thread-11899
final int f_msgID = 2;
Looper.prepare();// looper begin
final Timer f_timer = new Timer();
final Handler f_handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == f_msgID) {
Log.e("c", Thread.currentThread().getName());//thread-11899
}
}
};
TimerTask task = new TimerTask() {
@Override
public void run() {
Message message = new Message();
message.what = f_msgID;
f_handler.sendMessage(message);
Log.e("d", Thread.currentThread().getName());// timer-0
}
};
f_timer.schedule(task, 10, 10000);
Looper.loop();// looper end
}
}).start();
}
}
从这个过程中我们可以看出,Handler和 Log.e("b", Thread.currentThread().getName()) 所处的线程都在Thread-11899中,这个线程编号是程序自动指定的。
上面我们介绍这个Handler和TimerTask的比较。视图组件有一个特性,就是修改该组件只能在创建该组件的原始线程中完成,如果创建的视图组件的线程和修改视图组件的线程不在同一个线程中,那么就会报错。而有时候,我们又希望在非创建组件的线程中修改组件,那么这时候,就可以应用上的特性。
【Android】Android实现Handler异步详解的更多相关文章
- Android App优化之ANR详解
引言 背景:Android App优化, 要怎么做? Android App优化之性能分析工具 Android App优化之提升你的App启动速度之理论基础 Android App优化之提升你的App ...
- Android Telephony分析(三) ---- RILJ详解
前言 本文主要讲解RILJ工作原理,以便更好地分析代码,分析业务的流程.这里说的RILJ指的是RIL.java (frameworks\opt\telephony\src\java\com\andro ...
- 【Android 应用开发】Ubuntu 下 Android Studio 开发工具使用详解 (旧版本 | 仅作参考)
. 基本上可以导入项目开始使用了 ... . 作者 : 万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/21035637 ...
- Android高效率编码-第三方SDK详解系列(一)——百度地图,绘制,覆盖物,导航,定位,细腻分解!
Android高效率编码-第三方SDK详解系列(一)--百度地图,绘制,覆盖物,导航,定位,细腻分解! 这是一个系列,但是我也不确定具体会更新多少期,最近很忙,主要还是效率的问题,所以一些有效的东西还 ...
- 【Android 应用开发】Ubuntu 下 Android Studio 开发工具使用详解
. 基本上可以导入项目开始使用了 ... . 作者 : 万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/21035637 ...
- Android Telephony分析(五) ---- TelephonyRegistry详解
本文紧接着上一篇文章<Android Telephony分析(四) —- TelephonyManager详解 >的1.4小节.从TelephonyRegistry的大部分方法中: 可以看 ...
- Android Telephony分析(二) ---- RegistrantList详解
前言 本文主要讲解RegistrantList的原理,以及如何快速分析RegistrantList相关的代码流程.在Telephony模块中,在RIL.Tracker(ServiceStateTrac ...
- Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)
Android XML shape 标签使用详解 一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...
- Android图片缓存之Bitmap详解
前言: 最近准备研究一下图片缓存框架,基于这个想法觉得还是先了解有关图片缓存的基础知识,今天重点学习一下Bitmap.BitmapFactory这两个类. 图片缓存相关博客地址: Android图片缓 ...
随机推荐
- mysql下载安装使用教程
今天花了点时间终于把mysql安装好了,哈哈!下面上干货! (1)从官网下载mysql.地址https://www.mysql.com/ 图:按照图上的步骤就能找到 a.首页点击 DOWNLOA ...
- 【Python】torrentParser1.00
代码: #------------------------------------------------------------------------------------ # torrentP ...
- Linux(CentOS)中使用Mono+jexus部署Asp.net4.5网站
一.效果: 二.安装步骤: 1.安装系统CentOS,我这是用CentOs7测试的. 2.接下来安装libgdiplus.Mono.Jexus有问题可以参考安装工具的官网: Libgdiplus下载官 ...
- Go语言使用Beego的ORM插入Mysql后,时区不一致的解决方案
一.解决方案: 方案一: orm.Debug = false orm.DefaultTimeLoc = time.UTC orm.RegisterDriver("mysql", o ...
- mysql版本导致的hibernate 方言问题
今天在看hibernate视频时,看到视频上人家的hibernate.cfg.xml配置文件在配置hibernate方言时,发现视频上是这样写的<property name="dial ...
- [memory]虚拟地址空间分布
一.开篇 踏入嵌入式软件行业也接近2年了,从研一开学起懵懵懂懂的開始学习C语言.因为本科时对这方面了解的少之又少,所以学起来比較困难.可是有一群无私奉献的小伙伴,慢慢的,慢慢的,慢慢的,一仅仅脚踏进了 ...
- ES6学习笔记一:let、const、解构赋值
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/7236342.html 感谢阮一峰老师的无私奉献,开源推动世界!教程地址:http://es6.ruanyife ...
- js自动补全空白列(即缺少td的列)
//自动补全空白列 var rows = document.getElementById("gridTable").rows; //行对象 var allcells = rows[ ...
- 怎样使用Fiddler获取WebApi的token值?
User-Agent: Fiddler Host: localhost: Content-Length: Content-Type: application/json grant_type=passw ...
- 〖Android〗利用droidsshd在Android手机中开启 sshd,sftp,..
源码下载地址: src: git clone https://code.google.com/p/droidsshd/ apk: http://droidsshd.googlecode.com/fil ...