在android版本4.0及之后的版本中多线程有明确的分工,子线程可以写所有耗时的代码(数据库、蓝牙、网络服务),但是绝对不能碰UI,想碰UI跟着主线程走,那么我们如何才能让主线程知道我们要对 UI进行操作呢?这时我们就可以利用用消息机制——handler去通知主线程(因为子线程本身不可以发消息)

  下面是handler简单的工作原理图(此图为转载)

   handler用来发消息和处理消息

下面用个案例来说明:

  activity_main.xml:

      

 <RelativeLayout 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"
> <TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" /> <Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignTop="@+id/textView1"
android:layout_marginRight="53dp"
android:text="Button" /> <ListView
android:id="@+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/button1"
android:layout_marginTop="84dp" >
</ListView> <!-- <ProgressBar
android:id="@+id/progressBar1"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/listView1"
android:layout_alignRight="@+id/button1"
android:layout_below="@+id/button1"
android:layout_marginTop="28dp" /> --> </RelativeLayout>

listview中的布局item.xml

 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<TextView
android:id="@+id/username"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="60dp"
android:textSize="45dp"
/> <TextView
android:id="@+id/sex"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_weight="1"
android:textSize="45dp" /> </LinearLayout>

User.java(用于模拟数据)

 public class User {
private String username;
private String sex;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
} }

mainActivity.java

 

 import java.util.ArrayList;
import java.util.List; import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast; public class MainActivity extends Activity { private String fromDb_str1 = "";
private Button btn;
private TextView tv;
private ListView lv;
private BaseAdapter adapter;
private List<User> userList = new ArrayList<User>();
private Runnable doInBackground1;
private Runnable doInBackground2; //1.跟着主线程走,可以碰UI
//2.能够接受子线程发送的消息(Message)
// 子线程类本身不可以发信息
private Handler handler; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); Log.i("UI_MainThread","id:"+Thread.currentThread().getId()); //模拟数据访问产生数据
for (int i = 0; i < 5; i++) {
User u = new User();
u.setUsername("小明"+i);
u.setSex("女"+i);
userList.add(u);
} tv =(TextView)findViewById(R.id.textView1);
btn =(Button)findViewById(R.id.button1);
btn.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
//1.访问数据库或者互联网(但会卡的)
//2.更新界面
Thread t1 = new Thread(doInBackground1);
t1.start(); Thread t2 = new Thread(doInBackground2);
t2.start(); }
});
adapter = new BaseAdapter(){ @Override
public int getCount() {
// TODO Auto-generated method stub
return userList.size();
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = MainActivity.this.getLayoutInflater();
View view;
if (convertView==null){
view = inflater.inflate(R.layout.item, null);
}
else{
view = convertView;
} TextView tv_username = (TextView)view.findViewById(R.id.username);
TextView tv_sex = (TextView)view.findViewById(R.id.sex);
tv_username.setText(userList.get(position).getUsername());
tv_sex.setText(userList.get(position).getSex());
return view;
} @Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
} @Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
};
lv = (ListView)findViewById(R.id.listView1);
lv.setAdapter(adapter); handler = new Handler(){ //1.消息msg来自于子线程
//2.消息可以多个,采用msg.what识别
//3.处理消息,一般就会更新UI
//4.此方法可以参考onPostExecute
@Override
public void handleMessage(Message msg) { super.handleMessage(msg);
int msgwhat = msg.what;
Log.i("handler","已经收到消息,消息what:"+msgwhat+",id:"+Thread.currentThread().getId()); if (msgwhat==1){
//更新helloworld
tv.setText("子线程让我更新"+msgwhat);
}
if (msgwhat==2){
//更新ListView
adapter.notifyDataSetChanged();
} } }; //子线程代码1
doInBackground1 = new Runnable() { @Override
public void run() {
Log.i("sub_Thread","子线程1启动,id:"+Thread.currentThread().getId()); try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} //1.访问数据库或者互联网,不在UI进程,所以不卡
Message msg = new Message();
//对消息一个识别号,便于handler能够识别
msg.what = 1;
handler.sendMessage(msg);
Log.i("sub_Thread","子线程1已经发送消息给handler");
}
}; //子线程代码1
doInBackground2 = new Runnable() { @Override
public void run() {
Log.i("sub_Thread","子线程2启动,id:"+Thread.currentThread().getId()); try {
Thread.sleep(6000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} Message msg = new Message();
//对消息一个识别号,便于handler能够识别
msg.what = 2;
//handler.sendMessage(msg);
handler.sendMessageDelayed(msg, 500); //访问互联网,下载最新的,更新data,但不碰界面
for (User user : userList) {
user.setSex("不男不女");
} Log.i("sub_Thread","子线程2已经发送消息给handler");
}
}; }
}

效果图:

  点击button的时候如下图

上面就是一个小例子;但是上面的代码写的还有很多需要改进的地方,详情请参考(此链接为转载):

Android中使用Handler造成内存泄露的分析和解决http://www.linuxidc.com/Linux/2013-12/94065.htm

    

  

android——handler机制原理的更多相关文章

  1. Android Handler 机制总结

    写 Handler 原理的文章很多,就不重复写了,写不出啥新花样.这篇文章的主要是对 handler 原理的总结. 1.Android消息机制是什么? Android消息机制 主要指 Handler ...

  2. android handler工作原理

    android handler工作原理 作用 便于在子线程中更新主UI线程中的控件 这里涉及到了UI主线程和子线程 UI主线程 它很特别.通常我们会认为UI主线程将页面绘制完成,就结束了.但是它没有. ...

  3. 深入理解 Android 消息机制原理

    欢迎大家前往腾讯云社区,获取更多腾讯海量技术实践干货哦~ 作者:汪毅雄 导语: 本文讲述的是Android的消息机制原理,从Java到Native代码进行了梳理,并结合其中使用到的Epoll模型予以介 ...

  4. Android Handler机制彻底梳理

    Android的消息机制其实也就是Handler相关的机制,对于它的使用应该熟之又熟了,而对于它的机制的描述在网上也一大堆[比如15年那会在网上抄了一篇https://www.cnblogs.com/ ...

  5. android handler 调用原理

    1,调度原理 andriod提供了Handler 和 Looper 来满足线程间的通信.Handler先进先出原则.Looper类用来管理特定线程内对象之间的消息交换(MessageExchange) ...

  6. Android Handler 机制 - Looper,Message,MessageQueue

    Android Studio 2.3 API 25 从源码角度分析Handler机制.有利于使用Handler和分析Handler的相关问题. Handler 简介 一个Handler允许发送和处理M ...

  7. android Handler机制之ThreadLocal详解

    概述 我们在谈Handler机制的时候,其实也就是谈Handler.Message.Looper.MessageQueue之间的关系,对于其工作原理我们不做详解(Handler机制详解). Messa ...

  8. Android Handler机制剖析

    android的handler机制是android的线程通信的核心机制 Android UI是线程不安全的,如果在子线程中尝试进行UI操作,程序就有可能会崩溃. Android中的实现了 接收消息的& ...

  9. Android Handler机制 (一个Thead中可以建立多个Hander,通过msg.target保证MessageQueue中的每个msg交由发送message的handler进行处理 ,但是 每个线程中最多只有一个Looper,肯定也就一个MessageQuque)

    转载自http://blog.csdn.net/stonecao/article/details/6417364 在android中提供了一种异步回调机制Handler,使用它,我们可以在完成一个很长 ...

随机推荐

  1. 解决Maven项目pom.xml文件报xxx\target\classes\META-INF\MANIFEST.MF (系统找不到指定的路径。)问题

    最近自己在公司项目修改一些代码以后,出现如题的错误,后来各种Google等,最终找到了解决办法. 错误环境:Tomcat7 + Eclipse + Maven + Spring + SpringMvc ...

  2. 【转载】maven插件mybatis-generator自动生成 (1)

    http://blog.csdn.net/itlqi/article/details/49534447 1.新建一个maven项目在pom.xml添加如下: <plugins> <p ...

  3. cnetos7.0 安装mysql

    CentOS 7的yum源中貌似没有正常安装mysql时的mysql-sever文件,需要去官网上下载 [root@localhost ~]# wget http://dev.mysql.com/ge ...

  4. ubuntu系统怎么分区

    首先科普下windows和linux的文件系统和主分区: 1.电脑的主分最多只有只能由四个.如果是win7和linux双系统,则windows系统可能会占到1-2个主分区,那linux最多只能有两个主 ...

  5. Java面试常见知识点总结(三)

    21.volatile关键字: 一旦一个共享变量(类的成员变量.类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:   (1) 保证了不同线程对这个变量进行操作时的可见性,即一个线程 ...

  6. APP产品交互设计分析总结(不断更新中...)

    1.首页中的最下方的TAB和中部的TAB的区别 最下面的tab按钮应该是核心级模块级的大功能入口 中间的按钮应该是次核心级页面级的小功能入口 2.对于编辑是在单页内实现好还是跳转到新页面实现好 内容比 ...

  7. Html和CSS布局技巧

    单列布局水平居中 水平居中的页面布局中最为常见的一种布局形式,多出现于标题,以及内容区域的组织形式,下面介绍四种实现水平居中的方法(注:下面各个实例中实现的是child元素的对齐操作,child元素的 ...

  8. Python-Hello world!

    一.Python安装 Windows 1.下载安装包 https://www.python.org/downloads/ 2.安装 默认安装路径:C:\python3.5 3.配置环境变量: [右键计 ...

  9. C++ 代码优化

    1.类中所有的属性全部设置为private 然后在需要在外部调用的属性,每个都自己写Get方法返回,或者用Set方法设置 2.类成员变量采用m_前缀,代表类成员 3.采用单例模式 //设置类名为CCo ...

  10. 【转】CentOS上部署PPTP和L2TP over IPSec简要笔记

    PPTP部署 安装 PPTP 需要 MPPE 和较高版本的 ppp ( > 2.4.3 ) 支持,不过 CentOS 5.0/RHEL 5 的 2.6.18 内核已经集成了 MPPE 和高版本的 ...