Handler消息机制
Handler的定义:
主要接受子线程发送的数据, 并用此数据配合主线程更新UI.
解释: 当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程) , 主线程为管理界面中的UI控件,进行事件分发, 比如说, 你要是点击一个 Button ,Android会分发事件到Button上,来响应你的操作。 如果此时需要一个耗时的操作,例如: 联网读取数据, 或者读取本地较大的一个文件的时候,你不能把这些操作放在主线程中,,如果你放在主线程中的话,界面会出现假死现象, 如果5秒钟还没有完成的话,,会收到Android系统的一个错误提示 "强制关闭". 这个时候我们需要把这些耗时的操作,放在一个子线程中,因为子线程涉及到UI更新,,Android主线程是线程不安全的,也就是说,更新UI只能在主线程中更新,子线程中操作是危险的. 这个时候,Handler就出现了.,来解决这个复杂的问题 , 由于Handler运行在主线程中(UI线程中), 它与子线程可以通过Message对象来传递数据, 这个时候,Handler就承担着接受子线程传过来的(子线程用sedMessage()方法传弟)Message对象,(里面包含数据) , 把这些消息放入主线程队列中,配合主线程进行更新UI。
本程序功能: 利用Handler实现时间和图片的持续更新
xml文件:
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical" 6 android:gravity="center_horizontal"> 7 8 <ImageView 9 android:id="@+id/iv" 10 android:layout_width="wrap_content" 11 android:layout_height="wrap_content" 12 android:src="@drawable/ic_launcher"/> 13 <TextView 14 android:id="@+id/tv" 15 android:layout_width="wrap_content" 16 android:layout_height="wrap_content" 17 /> 18 </LinearLayout>
java代码如下:
1 import java.text.SimpleDateFormat; 2 import java.util.Date; 3 import java.util.Timer; 4 import java.util.TimerTask; 5 6 import android.annotation.SuppressLint; 7 import android.app.Activity; 8 import android.os.Bundle; 9 import android.os.Handler; 10 import android.os.Message; 11 import android.widget.ImageView; 12 import android.widget.TextView; 13 14 @SuppressLint("SimpleDateFormat") 15 public class HanderActivity extends Activity { 16 // 控制时间的更新 17 private static final int Time = 1; 18 // 控制图片的更新 19 private static final int Imge = 2; 20 private ImageView iv; 21 private TextView tv; 22 private int index = 0; 23 private int[] sorce = { R.drawable.img1, R.drawable.img2, R.drawable.img3, 24 R.drawable.img4, R.drawable.img5, R.drawable.img6, R.drawable.img7, 25 R.drawable.img8 }; 26 private SimpleDateFormat format = new SimpleDateFormat( 27 "yyyy年-MM月-dd日 HH时:mm分:ss秒"); 28 29 /* (non-Javadoc) 30 * @see android.app.Activity#onCreate(android.os.Bundle) 31 */ 32 @SuppressLint("HandlerLeak") 33 @Override 34 protected void onCreate(Bundle savedInstanceState) { 35 super.onCreate(savedInstanceState); 36 setContentView(R.layout.activity_hander); 37 iv = (ImageView) findViewById(R.id.iv); 38 tv = (TextView) findViewById(R.id.tv); 39 40 41 // Android应用中,我们页面都是主线程或UI线程中进行呈现,如果我们在我们UI线程中进行耗时性操作的话,我们UI线程就会出现ANR(Application 42 // not respose),所以我们要子线程中进行耗时性操作内容,但是这样有不容易触及我们UI控件,所以Android提供了Handler,用于在主线程和子线程之间传递和接受消息 43 44 45 final Handler hander = new Handler() { 46 //重写handlerMessage()方法 47 @Override 48 public void handleMessage(Message msg) { 49 if (msg.what == Time) { 50 Bundle data = msg.getData(); 51 String time = data.getString("time"); 52 tv.setText(time); 53 } else if (msg.what == Imge) { 54 Bundle data = msg.getData(); 55 int image = data.getInt("img"); 56 iv.setImageResource(sorce[image]); 57 } 58 } 59 60 }; 61 // 开启一个子线程,用于进行耗时的操作,完成后向hander发送数据 62 //此线程是控制时间更新的 63 new Thread() { 64 public void run() { 65 while (true) { 66 Message msg = new Message(); 67 //指定类型 68 msg.what = Time; 69 Bundle b = new Bundle(); 70 //向Bundle中放入数据 71 b.putString("time", format.format(new Date())); 72 //指定数据 73 msg.setData(b); 74 //向handler发送数据 75 hander.sendMessage(msg); 76 try { 77 //每隔一秒更新一次时间 78 sleep(1000); 79 } catch (InterruptedException e) { 80 e.printStackTrace(); 81 } 82 } 83 }; 84 85 }.start(); 86 87 /**开启一个定时器,用于定时更新图片的。 88 *第一个参数:类似Runnable接口 89 第二个参数:第一次执行延迟多久 90 第三个参数:就是以后执行的周期,多长时间执行一次 91 */ 92 new Timer().schedule(new TimerTask() { 93 94 @Override 95 public void run() { 96 /**防止数组下标越界,如果达到最大值让index重新置为0,*/ 97 if (index == sorce.length) { 98 index = 0; 99 } 100 Message msg = new Message(); 101 msg.what = Imge; 102 Bundle b = new Bundle(); 103 b.putInt("img", index); 104 msg.setData(b); 105 hander.sendMessage(msg); 106 index++; 107 108 } 109 }, 0, 1000); 110 111 } 112 113 }
运行的效果是:图片和时间每隔一秒就会变化一次。