Handler具体解释
首先下载Android api 进行查阅 ,API下载地址:http://pan.baidu.com/s/1i33dTGT
以下的描写叙述假设那里错了,请大家吐槽,我也是第一次学习,共同进步
Handler能够分发Message对象和Runnable对象到主线程中,每一个Handler实例,都会绑定到创建他的线程中(通常是位于主线程),它有两个作用:
(1): 安排消息或Runnable 在某个主线程中某个地方运行,
(2)安排一个动作在不同的线程中运行。
Looper 是管理Message
queue的类。
能够通过Looper.getMainLooper();获取主线程
以下通过两个实例来測试一下吧:
============================================ONE=================================================
第一个小Demo就是两个Button和一个ProgressBar ,xml文件的内容就不写了,直接看Activity的代码吧
package com.example.handler; import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.app.Activity;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar; public class MainActivity extends Activity { //声明各个控件
private Button start=null;
private Button end=null;
private ProgressBar progressbar=null;
private Thread thread=null;
//获取主线程(具体请看Android API 文档)
Looper looper=Looper.getMainLooper(); @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); //通过id找到他们
start=(Button)findViewById(R.id.start);
end=(Button)findViewById(R.id.end);
progressbar=(ProgressBar)findViewById(R.id.progressbar);
// 为Button设置监听器
start.setOnClickListener(new StartButtonOnclickListener());
end.setOnClickListener(new EndButtonOnclickListener()); } //声明点解開始类
class StartButtonOnclickListener implements OnClickListener{ @Override
public void onClick(View v)
{
progressbar.setVisibility(View.VISIBLE);
thread=new Thread(){
int i=0;
public void run(){
i+=10;
Message msg=handler.obtainMessage();
msg.arg1=i;
//让线程延迟
try{
Thread.sleep(2000);
}catch(InterruptedException e){
e.printStackTrace();
}
//Log.i("run", "run "+i+"%");
Log.i("run", Thread.currentThread().getName()+"====");
msg.sendToTarget();
}
};
thread.start();
} }
//结束的类
class EndButtonOnclickListener implements OnClickListener{ @Override
public void onClick(View v) {
//从message queue 中去掉run
handler.removeCallbacks(thread);
//让progressbar置成隐藏
progressbar.setVisibility(View.GONE);
} } Handler handler = new Handler(looper){
public void handleMessage(android.os.Message msg) { int i =msg.arg1;
//依据message中传来的參数控制进度条
/*
* 由于安卓不同意我们在主线程之外的线程中对UI进行改动,所以我在新建的线程中仅仅是进行计数
* 然后将计数的结果通过message传递到主线程中,在主线程中更新进度条。
*/
progressbar.setProgress(i);
Log.i("run", Thread.currentThread().getName());
if(i<100){
handler.post(thread);
}else{
handler.removeCallbacks(thread);
progressbar.setVisibility(View.GONE);
}
};
}; /*
* 第一次打印线程是在另外一个线程中,后面你的循环使用handler.post的话,这个runnable不会跑在子线程中,
* 而是把runnable放入了handler绑定的target(在此为主线程)中相应的队列,然后在handleMessage中通过looper
* 从队列取出runnable运行
*/
}
当我点击启动button后,调用的不是主线程的run,而是我新建的线程。 可是由于安卓不同意我们在主线程之外的线程中对UI进行改动,所以我在新建的线程中仅仅是进行计数,然后将计数的结果通过message传递到主线程中,在主线程中更新进度条。第一次运行,是在onclick中运行thread.start();
这条语句运行的,所以第一次计数是在新的线程里;然后在新的线程里,又运行了msg.sendToTarget(); 这个触发了Handler的handleMessage()方法,在这种方法里通过handler.post(thread);第二次运行了计数(通过这样形成了循环),因为post的机制,是把post的内容放到Handler绑定的线程(代码中绑定的是主线程(looper获取的是主线程))的message
queue中,所以我们看打印的结果是这种:
所以仅仅有一次是次线程运行的,剩余的都是主线程运行的。
====================================================================================SECOND===============================================================================
经过改进后:
package com.example.handler; import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.app.Activity;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar; public class MainActivity extends Activity { private Button start=null;
private Button end=null;
private ProgressBar progressbar=null;
private Thread thread=null; private static boolean running=true;
//获取主线程
Looper looper=Looper.getMainLooper(); @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); //通过id找到他们
start=(Button)findViewById(R.id.start);
end=(Button)findViewById(R.id.end);
progressbar=(ProgressBar)findViewById(R.id.progressbar); start.setOnClickListener(new StartButtonOnclickListener());
end.setOnClickListener(new EndButtonOnclickListener()); } class StartButtonOnclickListener implements OnClickListener{ @Override
public void onClick(View v)
{
progressbar.setVisibility(View.VISIBLE);
thread=new Thread(){
int i=0;
public void run(){
while(running){
i+=10;
Message msg=handler.obtainMessage();//返回从全局消息池中一个新的消息
msg.arg1=i;
//让线程延迟
try{
Thread.sleep(2000);
}catch(InterruptedException e){
e.printStackTrace();
}
Log.i("run", Thread.currentThread().getName()+"====");
msg.sendToTarget();
if(i>100){
//当计数超过一百时,跳出循环
running = false;
}
} }
};
thread.start();
} }
Handler handler = new Handler(looper){
public void handleMessage(android.os.Message msg) {
int i =msg.arg1;
progressbar.setProgress(i);
Log.i("run", Thread.currentThread().getName());
if(i>100){
//假设进度条慢,进度条隐藏
progressbar.setVisibility(View.GONE);
}
};
};
class EndButtonOnclickListener implements OnClickListener{
@Override
public void onClick(View v) {
//点击取消button,分线程不再循环计数
running = false;
//让progressbar置成隐藏
progressbar.setVisibility(View.GONE);
}
} }
通过设置一个Boolean变量后,当running为true时,循环计数,并调用handler.sendMessage(msg)为主线程传递计数结果
执行后是:
这种话就能够看出主次线程一次运行,通过次线程传值给主线程后,主线程改变ProgressBar的值。(这里记住安卓不同意我们在主线程之外的线程中对UI(主线程)进行改动)!
大家吐槽吧。。。
Handler具体解释的更多相关文章
- Android Handler 具体解释
Android开发中常常使用Handler来实现"跨越线程(Activity)更新UI".本文将从源代码角度回答:为什么使用Handler可以跨线程更新UI?为什么跨线程更新UI一 ...
- Handler具体解释系列(四)——利用Handler在主线程与子线程之间互发消息
MainActivity例如以下: package cc.c; import android.app.Activity; import android.os.Bundle; import androi ...
- Handler具体解释系列(七)——Activity.runOnUiThread()方法具体解释
MainActivity例如以下: package cc.testui3; import android.os.Bundle; import android.view.View; import and ...
- Handler消息处理机制详解
之前一直只知道handler如何使用,不知道其中的工作原理,趁着新版本提测阶段比较空闲,及时做一个总结. 先看一下Google官方文档关于handler的解释: A Handler allows yo ...
- 闲话handle和handler
虽然handle和handler只有一个字符之差,但在计算机的世界里,含义却大相径庭. 1. 先说说handle 北京话说"一边儿玩儿去,玩勺子把儿去","勺子把儿&qu ...
- Handler 机制(一)—— Handler的实现流程
由于Android采用的是单线程模式,开发者无法在子线程中更新 UI,所以系统给我提供了 Handler 这个类来实现 UI 更新问题.本贴主要说明 Handler 的工作流程. 1. Handler ...
- 谷哥的小弟学前端(11)——JavaScript基础知识(2)
探索Android软键盘的疑难杂症 深入探讨Android异步精髓Handler 具体解释Android主流框架不可或缺的基石 站在源代码的肩膀上全解Scroller工作机制 Android多分辨率适 ...
- J.U.C ThreadPoolExecutor解析
Java里面线程池顶级接口是Executor,但严格意义上讲Executor并不是一个线程池,而是一个线程执行工具,真正的线程池接口是ExecutorService.关系类图如下: 首先Executo ...
- Java 多线程之线程池的使用
一. 使用背景 谈到Java多线程,我们很自然的会想到并发,在编写多线程代码时,我们一般会创建多个线程,如果并发的线程数量很多,而且每个线程都是执行一个时间很短的任务就结束了,这样频繁的进行线程的创建 ...
随机推荐
- Loadrunner中与事务相关的概念及函数
一.事务 事务是指用户在客户端做一种或多种业务所需要的操作集,通过事务函数可以标记完成该业务所需要的操作内容:另一方面可以用来统计用户操作的相应时间.事务响应时间是指通过记录用户请求的开始时间和服务器 ...
- <测试用例设计>用户及权限管理功能常规测试方法
1) 赋予一个人员相应的权限后,在界面上看此人员是否具有此权限,并以此人员身份登陆,验证权限设置是否正确(能否超出所给予的权限): 2) 删除或修改已经登陆系统并正在进行操作的人员的权限,程序能否 ...
- django-grappelli 安装配置
在python34/scripts文件夹下pip3 install django-grappelli pip安装一般会装在python34的tools或lib之类的文件夹下,一定要找到那个文件夹,gr ...
- 骑士周游问题 --- 递归解法 --- java代码
骑士游历: 定义了向量的数组M,行数组X,列数组Y, 棋盘plane,计数器count,走动步数step 需要注意的是,递归函数的进入前的验证,原先的想法是传入来时的方向参数,可是这样的想法被实践否定 ...
- Python的数据处理学习(二)
本文参考Paul Barry所著的<Head First Python>一书,参考代码均可由http://python.itcarlow.ie/站点下载.本文若有任何谬误希望不吝赐教~ 二 ...
- sql-labs 分享
前段时间在网上发现了一个阿三同学托管在github上的sql注入入门科普项目,感觉挺不错,在此分享一下.虽然现在有很多工具比如sqlmap可以实现自动化的sql注入,但是个人感觉如果只知其然而不知其所 ...
- 【转】jsp页面中jstl标签详解
原文地址: JSLT标签库,是日常开发经常使用的,也是众多标签中性能最好的.把常用的内容,放在这里备份一份,随用随查.尽量做到不用查,就可以随手就可以写出来.这算是Java程序员的基本功吧,一定要扎实 ...
- fedora 16安装ByPass四网口网卡遇到的问题
这个问题困扰了好几天,今天终于在大谷歌的帮助下,在这个网站http://blog.bwysystems.com/bwysystems/?p=16上找到了答案!还是国外的技术论坛强,在百度上搜遍了也没有 ...
- Scene View Navigation
[Scene View Navigation] Hold the right mouse button to enter Flythrough mode. This turns your mouse ...
- Uvalive 4865 Data Recovery 最大流
题意就是 给一个50 * 50的矩阵 然后给出每行每列元素的和 和一个初始矩阵 矩阵中有些是未知,有些是已知 然后我们求目标矩阵就是把能确定的元素的值求出来,实在不能确定的就置为-1 所有矩阵元素的值 ...