博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android Handler 消息处理使用
阅读量:6094 次
发布时间:2019-06-20

本文共 5951 字,大约阅读时间需要 19 分钟。

本文内容

  • 环境
  • 演示 Handler 消息处理
  • 参考资料

Handler 有两个主要作用或者说是步骤:发送消息和处理消息。在新启动的线程中发送消息,在主线程中获取、并处理消息。Android 平台只允许UI线程修改 Activity 里的UI组件。

本文只给出核心代码,如果你是初学者,可以下载本文后面的源代码。

环境


  • Windows 2008 R2 64 位
  • Eclipse ADT V22.6.2,Android 4.4.3
  • 三星 SM-G3508,Android OS 4.1

 

演示 Handler 消息处理


演示主程序如下图 1 所示,有 4 个演示。

图 1 主程序

主程序 XML 页面,只是四个按钮,并为它们添加相应事件,显示 4 个演示的 Activity 而已,略,核心代码如下所示:

public class MainActivity extends Activity {
Handler handler = new Handler();
Intent intent = null;
 
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
 
findViewById(R.id.btn1).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
intent = new Intent(MainActivity.this, Handler1Demo.class);
startActivity(intent);
}
});
 
findViewById(R.id.btn2).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
intent = new Intent(MainActivity.this, Handler2Demo.class);
startActivity(intent);
}
});
 
findViewById(R.id.btn3).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
intent = new Intent(MainActivity.this, Handler3Demo.class);
startActivity(intent);
}
});
 
findViewById(R.id.btn4).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
intent = new Intent(MainActivity.this, Handler4Demo.class);
startActivity(intent);
}
});
}
}

加入和移除 Handler 到主线程

“加入”和“移除” Handler 到主线程,点击“开始”时,每隔1秒,将 Handler 加入到主线程队列中,执行 Runnable 中 run 方法内的代码,显示当前时间;点击“结束”时,从主线程队列移除  Handler。

图 2 加入和移除 Handler 到主线程

XML 页面包含三个组件:两个 Button,一个 TextView(TextView 在 ScrollView 内),略,核心代码如下所示:

public class Handler1Demo extends Activity {
private TextView tv = null;
private Button start = null;
private Button end = null;
 
Handler handler = new Handler();
// 线程每次执行时,输出时间,延时1秒加入主线程队列
Runnable r = new Runnable() {
public void run() {
tv.append(new Date().toLocaleString() + "\r\n");
handler.postDelayed(r, 1000);
}
};
 
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.handler_1_demo);
 
tv = (TextView) findViewById(R.id.text_view);
 
start = (Button) findViewById(R.id.start);
end = (Button) findViewById(R.id.end);
// 开始 将handler加入到主线程队列中
start.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
handler.post(r);
}
});
// 结束 从主线程队列中移除handler
end.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
handler.removeCallbacks(r);
}
});
}
}

定时 Handler

利用 Timer、TimerTask 和 Handler 定时刷新时间。

图 3 定时 Handler

XML 页面文件略,核心代码如下所示:

public class Handler2Demo extends Activity {
private TextView tv = null;
Timer timer = new Timer();
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
// 处理消息
tv = (TextView) findViewById(R.id.text_view);
tv.append(new Date().toLocaleString() + "\r\n");
break;
}
super.handleMessage(msg);
}
 
};
 
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.handler_2_demo);
 
timer.schedule(new TimerTask() {
public void run() {
Message message = new Message();
message.what = 1;
handler.sendMessage(message);
}
}, 0, 1000);
}
}

播放动画

跟前一个示例类似。

图 4 播放动画

XML 页面文件略,核心代码如下所示:

public class Handler3Demo extends Activity {
// 定义周期性显示的图片的ID
int[] imageIds = new int[] { R.drawable.java, R.drawable.ee,
R.drawable.ajax, R.drawable.xml, R.drawable.classic };
int currentImageId = 0;
 
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.handler_3_demo);
final ImageView show = (ImageView) findViewById(R.id.show);
final Handler myHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// 如果该消息是本程序所发送的
if (msg.what == 0x1233) {
// 动态地修改所显示的图片
show.setImageResource(imageIds[currentImageId++
% imageIds.length]);
}
}
};
// 定义一个计时器,让该计时器周期性地执行指定任务
new Timer().schedule(new TimerTask() {
@Override
public void run() {
// 发送空消息
myHandler.sendEmptyMessage(0x1233);
}
}, 0, 1200);
}
}

计算质数

这个一个更复杂的 Handler。计算从 2 开始,到你指定数之间的所有质数,并用 Toast 显示出来。

Handler 涉及如下几个组件:Message、Looper 和 MessageQueue。

  • Looper:每个线程只有一个 Looper,它负责管理 MessageQueue,不断从 MessageQueue 中取出消息,并将消息分给对应的 Handler 处理。
  • MessageQueue:由 Looper 负责管理。采用先进先出的方式管理 Message。
  • Handler:它能把消息发给 Looper 管理的 MessageQueue,并负责处理 Looper 分给它的消息。

图 5 计算质数

XML 页面文件略,核心代码如下所示:

public class Handler4Demo extends Activity {
static final String UPPER_NUM = "upper";
EditText etNum;
CalThread calThread;
 
// 定义一个线程类
class CalThread extends Thread {
public Handler mHandler;
 
public void run() {
Looper.prepare();
mHandler = new Handler() {
// 定义处理消息的方法
@Override
public void handleMessage(Message msg) {
if (msg.what == 0x123) {
int upper = msg.getData().getInt(UPPER_NUM);
List
nums = new ArrayList
();
// 计算从2开始、到upper的所有质数
outer: for (int i = 2; i <= upper; i++) {
// 用i处于从2开始、到i的平方根的所有数
for (int j = 2; j <= Math.sqrt(i); j++) {
// 如果可以整除,表明这个数不是质数
if (i != 2 && i % j == 0) {
continue outer;
}
}
nums.add(i);
}
// 使用Toast显示统计出来的所有质数
Toast.makeText(Handler4Demo.this, nums.toString(),
Toast.LENGTH_LONG).show();
}
}
};
Looper.loop();
}
}
 
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.handler_4_demo);
etNum = (EditText) findViewById(R.id.etNum);
calThread = new CalThread();
// 启动新线程
calThread.start();
}
 
// 为按钮的点击事件提供事件处理函数
public void cal(View source) {
// 创建消息
Message msg = new Message();
msg.what = 0x123;
Bundle bundle = new Bundle();
bundle.putInt(UPPER_NUM, Integer.parseInt(etNum.getText().toString()));
msg.setData(bundle);
// 向新线程中的Handler发送消息
calThread.mHandler.sendMessage(msg);
}
}

在新线程内创建了一个 Handler,由于在新线程中创建 Handler 时必须先创建 Looper,因此程序先调用 Looper.prepare() 方法为当前线程创建了一个 Looper实例,并创建配套的MessageQueue,新线程有了 Looper 对象后,接下来创建了一个Handler对象,该 Handler 可以处理其他线程发送过来的消息。程序最后调用了 Looper.loop() 的启动方法。

 

参考资料


 

转载地址:http://cggwa.baihongyu.com/

你可能感兴趣的文章
C++ 经典开源
查看>>
LayoutParams
查看>>
Chisel_LLDB调试命令
查看>>
DNS Doctoring
查看>>
(转载一篇)Windows7与ArcGIS Desktop9.3冲突问题解决(由QQ安装问题引出)(经本人验证已解决)...
查看>>
dedecms生成文档数据库崩溃 mysql daemon failed to start
查看>>
Linux的50个基本命令
查看>>
Objective-C中创建单例方法的步骤
查看>>
[转]无法安装MVC3,一直卡在vs10-kb2483190
查看>>
Codeforces 520B:Two Buttons(思维,好题)
查看>>
web框架-(二)Django基础
查看>>
Jenkins持续集成环境部署
查看>>
emoji等表情符号存mysql的方法
查看>>
Excel到R中的日期转换
查看>>
检查磁盘利用率并且定期发送告警邮件
查看>>
MWeb 1.4 新功能介绍二:静态博客功能增强
查看>>
linux文本模式和文本替换功能
查看>>
Windows SFTP 的安装
查看>>
摄像机与绕任意轴旋转
查看>>
rsync 服务器配置过程
查看>>