Android总结Handler异步更新UI界面

来源:互联网 发布:中级java程序员 编辑:程序博客网 时间:2024/04/29 15:42

本篇文章通过三种方式来实现UI控件的更新,Handler异步更新UI在安卓开发中最常用也非常实在。这篇文章注重实现思路,所以我就不在界面方面进行美化了,都是最原始的控件。有需要的可以收藏下,。虽说搜索引擎上关于Handler消息机制的文章已经数不尽数了,但是我写这篇文章也是希望在开发中能帮助自己记忆起Handler的用法。

学会使用Handler来更新UI,由于在主线程中直接更新UI会阻塞线程,造成假死现象,所以我们通常采用Handler消息机制在UI线程中来更新UI控件。至于Handler消息机制,在这里简单介绍一下。本来还打算写一种的,这里就不详细说了,通过在子线程使用Bundle封装属性到Message数据中,其次在Handler中解封装得到Message数据再显示到控件中。其原理与方法三无太大差别。


Handler消息机制原理简介:通过Handler对象向消息队列中Message Queue中发送消息Message,通过Looper对象来管理Queue中的Message。具体的大家可以查看Handler的源码。


好了,看到我们的效果图,三种方式实现的最终效果一致。



项目UI界面实现:3个Button,1个EditText,1个TextView。

项目实现原理:Handler机制实现UI更新。

项目逻辑实现:通过点击按钮获取输入框的时间并显示在一个TextView上,然后通过点击开始计时按钮开始倒计时,可以通过停止计时按钮停止计时。


实现方式一:Handler+Timer+TimerTask

通过该方式也是比较实用的,顾名思义,TimerTask计时器任务。由于Timer和TimerTask是同时出现的,TimerTask实现了Runnable接口,并且要求实现run方法。

首先,我们先编写我们的布局文件activity_main.xml,三种实现方式统一使用了该布局。

activity_main.xml

<LinearLayout 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:orientation="vertical"><EditText     android:id="@+id/inputTime"    android:layout_width="fill_parent"    android:layout_height="wrap_content"    android:singleLine="true"    android:hint="@null"/><Button    android:id="@+id/ensureTime"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:text="点击" /><TextView    android:id="@+id/showTime"    android:layout_width="fill_parent"    android:layout_height="wrap_content"/><Button    android:id="@+id/startTime"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:text="开始计时" /><Button    android:id="@+id/stopTime"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:text="停止计时" /></LinearLayout>

接下来就是我们的Activity实现步骤了。三种方式实现代码如下:


MainActivity.java

package com.mero.countTime;import java.util.Timer;import java.util.TimerTask;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;public class MainActivity extends Activity implements OnClickListener{private EditText inputTime;private TextView showTime;private Button ensureTime,startTime,stopTime;private Timer timer = null;private TimerTask task = null;private int i;//显示的倒计时数字    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initView();//实例化控件    }/**实例化控件方法*/private void initView() {inputTime = (EditText) findViewById(R.id.inputTime);showTime = (TextView) findViewById(R.id.showTime);ensureTime = (Button) findViewById(R.id.ensureTime);startTime = (Button) findViewById(R.id.startTime);stopTime = (Button) findViewById(R.id.stopTime);/**注册监听事件*/ensureTime.setOnClickListener(this);startTime.setOnClickListener(this);stopTime.setOnClickListener(this);};@Overridepublic void onClick(View v) {switch (v.getId()) {/**当选择点击按钮的监听事件*/case R.id.ensureTime:showTime.setText(inputTime.getText().toString());i=Integer.parseInt(inputTime.getText().toString());break;/**当选择开始计时按钮的监听事件*/case R.id.startTime:startTime();break;case R.id.stopTime:stopTime();break;}}/**当选择停止计时按钮的监听事件*/private Handler handler=new Handler(){/**重写handleMessage方法*/@Overridepublic void handleMessage(Message msg) {showTime.setText(msg.arg1+"");startTime();//执行计时方法}};/**开始计时方法*/private void startTime(){timer = new Timer();task = new TimerTask() {@Overridepublic void run() {i--;Message message = handler.obtainMessage();//获取Message对象message.arg1 = i;//设置Message对象附带的参数handler.sendMessage(message);//向主线程发送消息}};timer.schedule(task, 1000);//执行计时器事件};/**停止计时方法*/private void stopTime(){timer.cancel();//注销计时器事件};  }






实现方式二:Handler+postDelayed+post

MainActivity.java

package com.mero.countTime;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;public class MainActivity extends Activity implements OnClickListener{private EditText inputTime;//声明输入框private TextView showTime;//声明用于显示当前计时的时间private Button ensureTime,startTime,stopTime;//声明计时按钮,停止计时按钮和点击按钮private int i;//显示的倒计时数字private Runnable update;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initView();//实例化控件    }/**实例化控件方法*/private void initView() {inputTime = (EditText) findViewById(R.id.inputTime);showTime = (TextView) findViewById(R.id.showTime);ensureTime = (Button) findViewById(R.id.ensureTime);startTime = (Button) findViewById(R.id.startTime);stopTime = (Button) findViewById(R.id.stopTime);/**注册监听事件*/ensureTime.setOnClickListener(this);startTime.setOnClickListener(this);stopTime.setOnClickListener(this);};@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.ensureTime:showTime.setText(inputTime.getText().toString());//获取输入框上的时间并设置到显示文本控件上i=Integer.parseInt(inputTime.getText().toString());break;case R.id.startTime:startTime();//开始计时handler.post(update);break;case R.id.stopTime:stopTime();//停止计时break;}}final Handler handler=new Handler();/**开始计时方法*/private void startTime(){update=new Runnable(){@Overridepublic void run() {i--;showTime.setText(i+"");handler.postDelayed(update, 1000);//每隔1s将线程提交到线程队列中}};}/**停止计时方法*/private void stopTime(){handler.removeCallbacks(update);//移除Runnable对象};  }



实现方式三:Handler+Thread

MainActivity.java

package com.mero.countTime;import android.annotation.SuppressLint;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;public class MainActivity extends Activity implements OnClickListener{private EditText inputTime;private TextView showTime;private Button ensureTime,startTime,stopTime;private int i;//显示的倒计时数字private boolean flag;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initView();//实例化控件    }private void initView() {inputTime = (EditText) findViewById(R.id.inputTime);showTime = (TextView) findViewById(R.id.showTime);ensureTime = (Button) findViewById(R.id.ensureTime);startTime = (Button) findViewById(R.id.startTime);stopTime = (Button) findViewById(R.id.stopTime);/**注册监听事件*/ensureTime.setOnClickListener(this);startTime.setOnClickListener(this);stopTime.setOnClickListener(this);};@Overridepublic void onClick(View v) {switch (v.getId()) {/**点击按钮事件监听*/case R.id.ensureTime:showTime.setText(inputTime.getText().toString());i=Integer.parseInt(inputTime.getText().toString());break;/**开始按钮事件监听*/case R.id.startTime:flag=true;startTime();break;/**停止按钮事件监听*/case R.id.stopTime:stopTime();break;}}final Handler handler=new Handler(){public void handleMessage(Message msg) {int p=msg.what;showTime.setText(p+"");};};/**开始计时方法*/private void startTime() {/**开启一个新线程*/new Thread(){public void run() {/**每睡眠1秒后发送Message给Handler处理*/for(int j=i;j>=0;j--){if(flag==true){try {Thread.sleep(1000);Message msg=new Message();msg.what=j;//设置Message附带的参数handler.sendMessage(msg);//发送Message对象给Handleri=j;//将当前的时间传递给全局时间变量} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}}.start();}/**停止计时方法,通过设置boolean标志为false来停止*/@SuppressLint("NewApi")private void stopTime(){flag=false;};  }


通过上面的代码,我们来总结一下。


方法一:简单实用,尤其定时刷新控件,效果非常good,使用简单。注意Timer和TimerTask必须同时使用。使用Timer的schedule(task,delayed)方法提交TimerTask线程消息。由Handler处理线程消息。通过Timer.cancel(task)方式进行移除线程任务。


方法二:同方式一,简单实用,原理实质一致。通过实例化Runnable对象来构造实现run创建新线程,在新线程中不断将线程加入Looper池中进行处理。在主线程中通过post提交线程进行处理。通过handler.removeCallbacks(runnable)方式移除线程任务。


方法三:很经典实用的一种方式。通过for循环加上线程睡眠不断创建新消息。缺点是不易于控制,本文通过标志进行控制。


好了,本篇文章就到此结束了。如果还有什么问题的话,可以在下面留言。大家共同讨论共同进步。谢谢阅读 !

1 0