一、Handler
1.一个handler允许发送和处理Message和Ruanable对象,并且会关联到主线程的MessageQueue中。2.每个handler都具有一个独立的线程,并且关联到一个消息队列的线程。也就是说,没当实例化一个hanlder的时候,它就承载着一个线程和消息队列的线程。3.handler可以把Message或者Runnable压入到消息队列中,并且可以从消息队列中取出Message或者Runnable,进而操作它们。
Hndler的两个作用:
1.在工作线程中发送消息
2.在UI线程中获取。处理消息。
Handler把Message或者Runnable对象压入到消息队列中,有两大体系:
1. post:Post允许把一个 Runnable对象入队到消息队列中。它具有的方法为:post(Runnable)、postAtTime(Runnable,long)、postDelayed(Runnable,long)。
2. sendMessage:sendMessage允许把一个包含数据的 Message对象入队到消息队列中,它的方法有:sendEmptyMessage(int)、sendMessage(Message)、sendMessageAtTime(Message,long)、sendMessageDelayed(Message,long)。
Handler --- post:
1.removeCallbacks(Runnable):从消息队列中移除一个Runnable对象。2.boolean post(Runnable r):把一个Runnable入队到消息队列中,UI线程从消息队列中取出这个对象后,立即执行。
boolean postAtTime(Runnable r,long uptimeMillis):把一个Runnable入队到消息队列中,UI线程从消息队列中取出这个对象后,在特定的时间执行。
boolean postDelayed(Runnable r,long delayMillis):把一个Runnable入队到消息队列中,UI线程从消息队列中取出这个对象后,延迟delayMills秒执行
post(Runnable)、postAtTime(Runnable,long)、postDelayed(Runnable,long)这些方法中的Runnable对象中,需要重写run()方法,一般这个run()方法中写入需要在UI线程(主线程)上的操作。
例子:
1.在UI线程(主线程上执行代码)mes1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new Thread(new Runnable() {//---此时创建时,在子线程上。不能在子线程上更新UI @Override public void run() { mHandler.post(new Runnable() {//---此时在UI线程上,post方法 @Override public void run() { txt.setText("通过Post方法进行主线程上UI的更新!"); } }); } }).start(); } }); //延时执行 mes2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new Thread(new Runnable() { @Override public void run() { mHandler.postDelayed(new Runnable() { @Override public void run() { txt.setText("通过延迟执行而进行主线程上UI的更新!"); } },4004); } }).start(); } });
2.在子线程上执行获取网络上图片的操作:
onCreate()函数里面:创建一个Thread类:dialog = new ProgressDialog(this); dialog.setTitle("下载图片"); dialog.setMessage("下载中...,请稍等"); dialog.setCancelable(false); //网络图片下载 load.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new Thread(new myThread()).start();//开启子线程下载图片 //显示对话框 if(dialog != null){ dialog.show(); } } });
public class myThread implements Runnable{ private static final String image_url = "http://ww4.sinaimg.cn/bmiddle/786013a5jw1e7akotp4bcj20c80i3aao.jpg"; @Override public void run() { HttpClient httpClient = new DefaultHttpClient(); HttpGet httpGet = new HttpGet(image_url); HttpResponse httpResponse = null; try { httpResponse = httpClient.execute(httpGet); if(httpResponse.getStatusLine().getStatusCode() == 200){ byte[] data = EntityUtils.toByteArray(httpResponse.getEntity()); final Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); mHandler.post(new Runnable() { @Override public void run() { image.setImageBitmap(bitmap); } }); if(dialog != null && dialog.isShowing()){ dialog.dismiss(); } } } catch (IOException e) { e.printStackTrace(); } } }
Handler --- sendMessage:
Handler中,与Message发送消息相关的方法有:
1.Message obtainMessage():获取一个Message对象。
boolean sendMessage():发送一个Message对象到消息队列中,并在UI线程取到消息后,立即执行。
boolean sendMessageDelayed():发送一个Message对象到消息队列中,在UI线程取到消息后,延迟执行。
boolean sendEmptyMessage(int what):发送一个空的Message对象到队列中,并在UI线程取到消息后,立即执行。
boolean sendEmptyMessageDelayed(int what,long delayMillis):发送一个空Message对象到消息队列中,在UI线程取到消息后,延迟执行。
void removeMessage():从消息队列中移除一个未响应的消息。
整体例子:package com.wangpei.hanlder; import android.app.Activity; import android.app.ProgressDialog; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Handler; import android.os.Message; import android.support.v7.app.ActionBarActivity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils; import java.io.IOException; public class MainActivity extends Activity { private Button mes1; private Button mes2; private TextView txt; private Handler mHandler = new Handler(); private Button load; private ImageView image; private ProgressDialog dialog; private static final int IS_FINISH = 1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mes1 = (Button) findViewById(R.id.btn_mes1); mes2 = (Button) findViewById(R.id.btn_mes2); txt = (TextView) findViewById(R.id.txt); image = (ImageView) findViewById(R.id.image); load = (Button) findViewById(R.id.download); dialog = new ProgressDialog(this); dialog.setTitle("下载图片"); dialog.setMessage("下载中...,请稍等"); dialog.setCancelable(false); //网络图片下载 load.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new Thread(new myThread()).start();//开启子线程下载图片 //显示对话框 if(dialog != null){ dialog.show(); } } }); } private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { if(msg.what == IS_FINISH){ byte[] data = (byte[]) msg.obj; Bitmap bitmap = BitmapFactory.decodeByteArray(data,0,data.length); image.setImageBitmap(bitmap); if(dialog != null && dialog.isShowing()){ dialog.dismiss(); } } } }; public class myThread implements Runnable{ private static final String image_url = "http://ww4.sinaimg.cn/bmiddle/786013a5jw1e7akotp4bcj20c80i3aao.jpg"; @Override public void run() { HttpClient httpClient = new DefaultHttpClient(); HttpGet httpGet = new HttpGet(image_url); HttpResponse httpResponse = null; try { httpResponse = httpClient.execute(httpGet); if(httpResponse.getStatusLine().getStatusCode() == 200){ byte[] data = EntityUtils.toByteArray(httpResponse.getEntity()); final Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); Message message = Message.obtain(); message.obj = data; message.what = IS_FINISH; handler.sendMessage(message); } } catch (IOException e) { e.printStackTrace(); } } } }
解析:
首先需要创建一个Handler:这个Handler是用来处理接收到的消息。并且是在UI线程(主线程中执行的)private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { if(msg.what == IS_FINISH){ byte[] data = (byte[]) msg.obj; Bitmap bitmap = BitmapFactory.decodeByteArray(data,0,data.length); image.setImageBitmap(bitmap); if(dialog != null && dialog.isShowing()){ dialog.dismiss(); } } } };
然后,在子线程中使用Message来发送消息:其中,sendMessage就意在发送消息到hanlderMessa中。byte[] data = EntityUtils.toByteArray(httpResponse.getEntity()); Message message = Message.obtain(); message.obj = data; message.what = IS_FINISH; handler.sendMessage(message);
更多的Message使用方法:
package com.wangpei.hanlder; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.PersistableBundle; import android.view.View; import android.widget.Button; import android.widget.TextView; import org.w3c.dom.Text; /** * 作者:Wangpei on 2015/7/29 16:20 * 邮箱:460977141@qq.com */ public class MainActivity2 extends Activity implements View.OnClickListener{ private Button btn1; private Button btn2; private Button btn3; private Button btn4; private Button btn5; private TextView txt; //创建一个Handler对象 private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { if(msg.what == 3 || msg.what == 5){ txt.setText("what = "+msg.what+",这是一个空消息!"); }else{ txt.setText("what = "+msg.what+",内容是:"+msg.obj.toString()); } } }; @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.actvity_main2); btn1 = (Button) findViewById(R.id.button); btn2 = (Button) findViewById(R.id.button2); btn3 = (Button) findViewById(R.id.button3); btn4 = (Button) findViewById(R.id.button4); btn5 = (Button) findViewById(R.id.button5); txt = (TextView) findViewById(R.id.txt); btn1.setOnClickListener(this); btn2.setOnClickListener(this); btn3.setOnClickListener(this); btn4.setOnClickListener(this); btn5.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()){ //使用Hanlder.sendMessage()发送消息 case R.id.button:{ Message message = Message.obtain(); message.obj = "使用Hanlder.sendMessage()发送消息"; message.what = 1; handler.sendMessage(message); break; } //使用Message.sendToTarget()发送消息,这类方法可以直接使用 Message.sendToTarget()方法发送消息到消息队列中,这是因为在Message对象中有一个私有的Handler类型的属性 Target,当时obtain方法传递进一个Handler对象的时候,会给Target属性赋值,当调用sendToTarget()方法的时候,实 际在它内部还是调用的Target.sendMessage()方法。 case R.id.button2:{ Message message = Message.obtain(handler); message.what = 2; message.obj = "使用Message.sendToTarget()发送消息"; message.sendToTarget(); break; } //发送空消息 case R.id.button3:{ handler.sendEmptyMessage(3); break; } //使用Hanlder.sendMessage发送延迟消息 case R.id.button4:{ Message message = Message.obtain(); message.what = 4; message.obj = "使用Hanlder.sendMessage发送延迟消息"; handler.sendMessageDelayed(message,4000); break; } //发送延迟空消息 case R.id.button5:{ handler.sendEmptyMessageAtTime(5,4000); break; } } } }