Android之Handler消息机制
2016-03-02 16:00
483 查看
android中Handle类的主要作用:
1.在新启动的线程中发送给消息2.在主线程获取、处理消息
欢迎加入QQ交流3群:317874559
为什么要用Handle这样的一个机制:
因为在Android系统中UI操作并不是线程安全的,如果多个线程并发的去操作同一个组件,可能导致线程安全问题。为了解决这一个问题,android制定了一条规则:只允许UI线程来修改UI组件的属性等,也就是说必须单线程模型,这样导致如果在UI界面进行一个耗时叫长的数据更新等就会形成程序假死现象 也就是ANR异常,如果20秒中没有完成程序就会强制关闭。所以比如另一个线程要修改UI组件的时候,就需要借助Handler消息机制了。Handle发送和处理消息的几个方法:
1. void handleMessage( Message msg):处理消息的方法,该方法通常被重写。2.final boolean hasMessage(int what):检查消息队列中是否包含有what属性为指定值的消息
3.final boolean hasMessage(int what ,Object object) :检查消息队列中是否包含有what好object属性指定值的消息
4.sendEmptyMessage(int what):发送空消息
5.final Boolean send EmptyMessageDelayed(int what ,long delayMillis):指定多少毫秒发送空消息
6.final boolean sendMessage(Message msg):立即发送消息
7.final boolean sendMessageDelayed(Message msg,long delayMillis):多少秒之后发送消息
与Handle工作的几个组件Looper、MessageQueue各自的作用:
1.Handler:它把消息发送给Looper管理的MessageQueue,并负责处理Looper分给它的消息2.MessageQueue:采用先进的方式来管理Message
3.Looper:每个线程只有一个Looper,比如UI线程中,系统会默认的初始化一个Looper对象,它负责管理MessageQueue,不断的从MessageQueue中取消息,并将
相对应的消息分给Handler处理
在线程中使用Handler的步骤:
1.调用Looper的prepare()方法为当前线程创建Looper对象,创建Looper对象时,它的构造器会自动的创建相对应的MessageQueue2.创建Handler子类的实例,重写HandleMessage()方法,该方法处理除UI线程以外线程的消息
3.调用Looper的loop()方法来启动Looper
实例
[html]
view plain
copy
print?
<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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<EditText
android:id="@+id/ed1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number" />
<Button
android:id="@+id/Ok"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/ed1"
android:text="@string/Ok" />
<Button
android:id="@+id/next"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/Ok"
android:text="下一张" />
<ImageView
android:id="@+id/image1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/next"
android:src="@drawable/a3" />
</RelativeLayout>
<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" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <EditText android:id="@+id/ed1" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="number" /> <Button android:id="@+id/Ok" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/ed1" android:text="@string/Ok" /> <Button android:id="@+id/next" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/Ok" android:text="下一张" /> <ImageView android:id="@+id/image1" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/next" android:src="@drawable/a3" /> </RelativeLayout>
[java]
view plain
copy
print?
package com.android.xiong.handlertesttwo;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
//吗的 不知怎么的Toast显示的是好像一定要点下图片 显示的才能在屏幕上看到效果
private EditText ed1;
private Button ok1;
private Button next;
private ImageView image1;
private Thread th;
private static int s=1;
private int iamges[] = { R.drawable.a3, R.drawable.a4 };
private final String DATA = "data";
// 实现Runnable接口
class Rub implements Runnable {
public Handler myHandler;
// 线程体
@Override
public void run() {
Looper.prepare();
myHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
String ms = "";
if (msg.what == 0x123) {
int data = msg.getData().getInt(DATA);
//循环的时候界面依旧可以点击next按钮 这是本实例效果
for (int i = 0; i < data; i++) {
try {
//循环一次 暂停1秒
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
ms += String.valueOf(i) + " ";
Toast.makeText(getApplicationContext(), ms, Toast.LENGTH_LONG)
.show();
}
}
}
};
Looper.loop();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ed1 = (EditText) findViewById(R.id.ed1);
ok1 = (Button) findViewById(R.id.Ok);
next = (Button) findViewById(R.id.next);
image1 = (ImageView) findViewById(R.id.image1);
final Rub rub = new Rub();
//子线程中不能有UI组件进行操作
th = new Thread(rub);
// 启动线程
th.start();
ok1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Message msg = new Message();
msg.what = 0x123;
Bundle bundle = new Bundle();
bundle.putInt(DATA, Integer.parseInt(ed1.getText().toString()));
msg.setData(bundle);
rub.myHandler.sendMessage(msg);
}
});
//在UI线程中操作组件
next.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
image1.setImageResource(iamges[s++% iamges.length] );
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
package com.android.xiong.handlertesttwo;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;
public class MainActivity extends Activity {
//吗的 不知怎么的Toast显示的是好像一定要点下图片 显示的才能在屏幕上看到效果
private EditText ed1;
private Button ok1;
private Button next;
private ImageView image1;
private static int s=1;
private int iamges[] = { R.drawable.a3, R.drawable.a4 };
private final String DATA = "data";
public Handler myHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ed1 = (EditText) findViewById(R.id.ed1);
ok1 = (Button) findViewById(R.id.Ok);
next = (Button) findViewById(R.id.next);
image1 = (ImageView) findViewById(R.id.image1);
myHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
String ms = "";
if (msg.what == 0x123) {
int data = msg.getData().getInt(DATA);
//循环的时候界面依旧可以点击next按钮 这是本实例效果
for (int i = 0; i < data; i++) {
try {
//循环一次 暂停1秒
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
ms += String.valueOf(i) + " ";
Toast.makeText(getApplicationContext(), ms, Toast.LENGTH_LONG)
.show();
}
}
}
};
ok1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Message msg = new Message();
msg.what = 0x123;
Bundle bundle = new Bundle();
bundle.putInt(DATA, Integer.parseInt(ed1.getText().toString()));
msg.setData(bundle);
myHandler.sendMessage(msg);
}
});
//在UI线程中操作组件
next.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
image1.setImageResource(iamges[s++% iamges.length] );
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
其实Handler不仅可以更新UI,你完全可以在一个子线程中去创建一个Handler,然后使用这个handler实例在任何其他线程中发送消息,最终处理消息的代码都会在你创建Handler实例的线程中运行。
[java]
view plain
copy
print?
new Thread()
{
private Handler handler;
public void run()
{
Looper.prepare();
handler = new Handler()
{
public void handleMessage(android.os.Message msg)
{
Log.e("TAG",Thread.currentThread().getName());
};
};
Looper.loop();
}
new Thread() { private Handler handler; public void run() { Looper.prepare(); handler = new Handler() { public void handleMessage(android.os.Message msg) { Log.e("TAG",Thread.currentThread().getName()); }; };<div class="dp-highlighter bg_java"><div class="bar"><div class="tools"><strong>[java]</strong> <a target=_blank title="view plain" class="ViewSource" href="http://blog.csdn.net/lmj623565791/article/details/38377229#">view plain</a><span class="tracking-ad" data-mod="popu_168"> <a target=_blank title="copy" class="CopyToClipboard" href="http://blog.csdn.net/lmj623565791/article/details/38377229#" target="_blank">copy</a></span><span class="tracking-ad" data-mod="popu_169"> <a target=_blank title="print" class="PrintSource" href="http://blog.csdn.net/lmj623565791/article/details/38377229#" target="_blank">print</a></span><a target=_blank title="?" class="About" href="http://blog.csdn.net/lmj623565791/article/details/38377229#">?</a><span class="tracking-ad" data-mod="popu_167"><a target=_blank title="在CODE上查看代码片" style="text-indent: 0px;" href="https://code.csdn.net/snippets/445431" target="_blank"><img width="12" height="12" style="left: 2px; top: 1px; position: relative;" alt="在CODE上查看代码片" src="https://code.csdn.net/assets/CODE_ico.png" /></a></span><span class="tracking-ad" data-mod="popu_170"><a target=_blank title="派生到我的代码片" style="text-indent: 0px;" href="https://code.csdn.net/snippets/445431/fork" target="_blank"><img width="12" height="12" style="left: 2px; top: 2px; position: relative;" alt="派生到我的代码片" src="https://code.csdn.net/assets/ico_fork.svg" /></a></span></div></div><ol class="dp-j"><li class="alt"><span><span>Looper.loop(); } </span></span></li></ol></div><pre class="java" style="display: none;" name="code" snippet_file_name="blog_20140808_19_1943618" code_snippet_id="445431"> Looper.loop(); }
Android不仅给我们提供了异步消息处理机制让我们更好的完成UI的更新,其实也为我们提供了异步消息处理机制代码的参考~~不仅能够知道原理,最好还可以将此设计用到其他的非Android项目中去~~
相关文章推荐
- Android中shape中的属性大全
- Android:BaseListAdapter——提高开发效率的BaseAdapter
- Android多分辨率适配实践【1】使用字体图标(内含两枚神器)
- Android最佳性能实践
- Android中用Toast.cancel()方法优化toast内容的显示
- Android中如何做到Service被关闭后又自动启动
- Android应用开发中模拟按HOME键效果
- Android学习历程18-SeekBar的简单使用
- Android Studio编译好的apk放在哪里?
- DrawerLayoutAndroid如何通过点击事件打开
- android studio 学习笔记
- Android应用启动后自动创建桌面快捷方式
- 快速开发框架androidannotations
- Android开发中实现多点触摸
- Android学习历程17-popupWindow从下往上弹出效果的实现
- Android 自定义Activity基类与TitleBar
- Android夜间模式实现,通过在window上加一层半透明的View
- Android弹幕01
- android 中的文件储存
- Android View自动生成插件