在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. Python中内置数据类型list,tuple,dict,set的区别和用法

    Python中内置数据类型list,tuple,dict,set的区别和用法 Python语言简洁明了,可以用较少的代码实现同样的功能.这其中Python的四个内置数据类型功不可没,他们即是list, ...

  2. NYOJ之题目325 zb的生日

    -------------------------------------- 刷一辈子水题... AC代码: import java.util.Scanner; public class Main { ...

  3. Linux更改计算机名称

    1.修改:vim /etc/hosts 2.修改:vim /etc/sysconfig/network 3.重启:reboot 如不重启可以输入:hostname  新改的计算机名称,然后su

  4. hdu 1241 Oil Deposits

    #include<cstdio> #include<iostream> #include<algorithm> #include<math.h> #in ...

  5. PHP 判断点是否在多边形内

    如何判断一个点是否在一个多边形内,何时会用到这个场景. 我们就模拟一个真是场景.我们公司是快递公司,在本地区域有6个分点.每个分点有3-5个工人负责附近的快递派遣发送,所以根据每个点的服务区域我们就能 ...

  6. 比较完整的WebView的用法

    WebView, WebChromeClient和WebViewClient加载网页基本用法 webview是android中的浏览器控件,在一些手机应用中常会用到b/s模式去开发应用,这时webvi ...

  7. Unity IOS Build的Graphics API最好是固定Opengl ES 2.0

    不要选择Automatic也不要选择Metal,因为这个选项可能会导致app在Iphone6上出现crash. 一个类似的crash堆栈: http://stackoverflow.com/quest ...

  8. 安卓手持智能POS端上能扫描开单的软件-店面销售开单系统

    安卓移动POS终端上能扫描开单的软件: 一.登录验证,以业务员.密码登录: 二.订单列表,显示相关信息,包括日期.单据号.客户名.金额.单据状态.有新增订单及按特定条件查询订单的功能(日期.客户等). ...

  9. 使用极光推送(www.jpush.cn)向安卓手机推送消息【服务端向客户端主送推送】C#语言

    在VisualStudio2010中新建网站JPushAndroid.添加引用json帮助类库Newtonsoft.Json.dll. 在web.config增加appkey和mastersecret ...

  10. QT5之三大重要窗体

    当创建项目时,会发现编辑器提供三个基类,分别为:QMainWindow.QWidget.QDialog,三个基类的区别说明如下.1.QMainWindowQMainWindow类提供一个有菜单条.锚接 ...