Android系统规定,一些耗时的操作不能放在UI线程中去执行,这样会报一个ANR错误。所以为了避免该问题,我们需要开启一个新的线程去执行一些耗时操作;开启新的线程,将耗时的操作在新线程里面去执行, 但是子线程中不能更新UI界面,所以我们使用android的Handler机制可以解决这个问题。
详细解释如下:
当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程) , 主线程为管理界面中的UI控件,进行事件分发, 比如说, 你要是点击一个 Button ,Android会分发事件到Button上,来响应你的操作。 如果此时需要一个耗时的操作,例如: 联网读取数据, 或者读取本地较大的一个文件的时候,你不能把这些操作放在主线程中,如果你放在主线程中的话,界面会出现假死现象, 如果5秒钟还没有完成的话,,会收到Android系统的一个错误提示 "强制关闭". 这个时候我们需要把这些耗时的操作,放在一个子线程中,因为子线程涉及到UI更新,Android主线程是线程不安全的,也就是说,更新UI只能在主线程中更新,子线程中操作是危险的. 这个时候,Handler就出现了.,来解决这个复杂的问题 , 由于Handler运行在主线程中(UI线程中), 它与子线程可以通过Message对象来传递数据, 这个时候,Handler就承担着接受子线程传过来的(子线程用sedMessage()方法传弟)Message对象,(里面包含数据) , 把这些消息放入主线程队列中,配合主线程进行更新UI。
1。图示说明:
用一个实例来说明:
2.XML代码:
1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:paddingBottom="@dimen/activity_vertical_margin" 6 android:paddingLeft="@dimen/activity_horizontal_margin" 7 android:paddingRight="@dimen/activity_horizontal_margin" 8 android:paddingTop="@dimen/activity_vertical_margin" 9 tools:context=".MainActivity" > 10 11 <TextView 12 android:id="@+id/msg" 13 android:layout_width="wrap_content" 14 android:layout_height="wrap_content" /> 15 16 <Button 17 android:id="@+id/btn" 18 android:layout_width="wrap_content" 19 android:layout_height="wrap_content" 20 android:layout_centerHorizontal="true" 21 android:layout_centerVertical="true" 22 android:text="更新UI界面" /> 23 24 </RelativeLayout>
3.java代码:
1 package com.example.handler; 2 3 import android.os.Bundle; 4 import android.os.Handler; 5 import android.os.Message; 6 import android.app.Activity; 7 import android.view.Menu; 8 import android.view.View; 9 import android.view.View.OnClickListener; 10 import android.widget.Button; 11 import android.widget.TextView; 12 13 public class MainActivity extends Activity { 14 private Mythread mythread; 15 private TextView mTextView; 16 private Button mButton; 17 18 private final Handler handler = new Handler() { 19 public void handleMessage(Message msg) { 20 super.handleMessage(msg); 21 String name = (String) msg.obj; 22 int m = msg.arg1; 23 mTextView.append(name + m); 24 }; 25 }; 26 27 @Override 28 protected void onCreate(Bundle savedInstanceState) { 29 super.onCreate(savedInstanceState); 30 setContentView(R.layout.activity_main); 31 mTextView = (TextView) this.findViewById(R.id.msg); 32 mButton = (Button) this.findViewById(R.id.btn); 33 mButton.setOnClickListener(new OnClickListener() { 34 @Override 35 public void onClick(View arg0) { 36 mythread = new Mythread(); 37 new Thread(mythread).start(); 38 } 39 }); 40 } 41 42 private class Mythread implements Runnable { 43 @Override 44 public void run() { 45 int count = 0; 46 while (count <= 20) { 47 48 try { 49 Thread.sleep(500); 50 } catch (InterruptedException e) { 51 // TODO Auto-generated catch block 52 e.printStackTrace(); 53 } 54 Message message = Message.obtain();// 这里虽然可以new一个消息实例,但是最好别new. 55 message.arg1 = count; 56 message.obj = "summer"; 57 handler.sendMessage(message); 58 count++; 59 } 60 } 61 } 62 63 64 @Override 65 public boolean onCreateOptionsMenu(Menu menu) { 66 // Inflate the menu; this adds items to the action bar if it is present. 67 getMenuInflater().inflate(R.menu.main, menu); 68 return true; 69 } 70 }