Handler和AsyncTask
原文地址:https://blog.csdn.net/LogicTeamLeader/article/details/51165375
https://blog.csdn.net/logicteamleader/article/details/46591499
Handler:
要理解Handler,必然要综合理解Looper,Messagequeue,HandlerThread。
Looper:其中有一个Messagequeue,looper负责轮询Messagequeue,取出其中的Message交给Handler处理
Handler:负责处理Message。Handler的创建需要Looper对象,它创建时会自动匹配该线程的looper对象,若在子线程创建,需要looper.prepare()创建looper对象。(主线程本身就存在looper)
HandlerThread:顾名思义,Handler存在的线程,Handler在哪个线程创建就存在于哪个线程中。这个大部分时间都在执行looper.loop()方法。getlooper()可以获取当前线程的looper。
关系图:
具体的用法:
(1)主线程创建Handler
package com.example.wxbhandlertest; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.MessageQueue; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; /** * @author wxb * Android中的消息处理实例之一 * * 一、在主线程内发送消息 * 1.使用post * 2.使用postDelay * 3.使用sendMessage * 4.使用Message.sentToTarget * 二、在子线程中使用Handler * 1.使用post * 2.使用postDelay * 3.使用sendMessage * 4.使用Message.sentToTarget */ public class MainActivity extends Activity { private Runnable runnable=null; private Runnable runnableDelay=null; private Runnable runnableInThread=null; private Runnable runnableDelayInThread=null; private static TextView tv; private static TextView tvOnOtherThread; //自定义Message类型 public final static int MESSAGE_WXB_1 = 1; public final static int MESSAGE_WXB_2 = 2; public final static int MESSAGE_WXB_3 = 3; public final static int MESSAGE_WXB_4 = 4; public final static int MESSAGE_WXB_5 = 5; private static Handler mHandler=new Handler(){ @Override public void handleMessage(Message msg) { switch(msg.what){ case MESSAGE_WXB_1: tv.setText("invoke sendMessage in main thread"); break; case MESSAGE_WXB_2: tv.setText("Message.sendToTarget in main thread"); break; case MESSAGE_WXB_3: tvOnOtherThread.setText("invoke sendMessage in other thread"); break; case MESSAGE_WXB_4: tvOnOtherThread.setText("Message.sendToTarget in other thread"); break; } super.handleMessage(msg); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = (TextView) this.findViewById(R.id.tvOnMainThread); tvOnOtherThread = (TextView) this.findViewById(R.id.tvOnOtherThread); //方法1.post runnable = new Runnable(){ public void run(){ tv.setText(getString(R.string.postRunnable)); } }; Button handler_post = (Button) this.findViewById(R.id.btnHandlerpost); handler_post.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mHandler.post(runnable); } }); //方法2:postDelay runnableDelay = new Runnable(){ public void run(){ tv.setText(getString(R.string.postRunnableDelay)); } }; Button handler_post_delay = (Button) this.findViewById(R.id.btnHandlerPostdelay); handler_post_delay.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mHandler.postDelayed(runnableDelay, 1000); //1秒后执行 } }); //方法3:sendMessage Button btnSendMessage = (Button) this.findViewById(R.id.btnSendMessage); btnSendMessage.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Message msg = mHandler.obtainMessage(); msg.what = MESSAGE_WXB_1; mHandler.sendMessage(msg); } }); //方法4:Message.sendToTarget Button btnSendtoTarget = (Button) this.findViewById(R.id.btnSendtoTarget); btnSendtoTarget.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Message msg = mHandler.obtainMessage(); msg.what = MESSAGE_WXB_2; msg.sendToTarget(); } }); //在其他线程中发送消息 //1.post runnableInThread = new Runnable(){ public void run(){ tvOnOtherThread.setText(getString(R.string.postRunnableInThread)); } }; Button btnPost = (Button) this.findViewById(R.id.btnPost); btnPost.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { new Thread(){ @Override public void run() { super.run(); mHandler.post(runnableInThread); } }.start(); } }); //2.postDelay runnableDelayInThread = new Runnable(){ public void run(){ tvOnOtherThread.setText(getString(R.string.postRunnableDelayInThread)); } }; Button btnPostDelay = (Button) this.findViewById(R.id.btnPostDelay); btnPostDelay.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { new Thread(){ @Override public void run() { super.run(); mHandler.postDelayed(runnableDelayInThread, 1000); } }.start(); } }); //3.sendMessage Button btnSendMessage2 = (Button) this.findViewById(R.id.btnSendMessage2); btnSendMessage2.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { new Thread(){ @Override public void run() { super.run(); Message msg = mHandler.obtainMessage(); msg.what = MESSAGE_WXB_3; mHandler.sendMessage(msg); } }.start(); } }); //方法4:Message.sendToTarget Button btnSendToTarget2 = (Button) this.findViewById(R.id.btnSendToTarget2); btnSendToTarget2.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { new Thread(){ @Override public void run() { super.run(); mHandler.obtainMessage(MESSAGE_WXB_4).sendToTarget(); } }.start(); } }); } }
(2)子线程创建Handler
package com.example.wxbloopinthread; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class MainActivity extends Activity { private static TextView tv = null; //自定义Message类型 public final static int MESSAGE_WXB_1 = 1; //主线程中创建Handler private static Handler mHandler = new Handler(){ @Override public void handleMessage(Message msg) { switch(msg.what){ case MESSAGE_WXB_1: tv.setText("主线程发送,子线程接收消息后回发,主线程修改UI"); break; } super.handleMessage(msg); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = (TextView) this.findViewById(R.id.textView1); //创建子线程 new LooperThread().start(); //点击按钮向子线程发送消息 Button btn = (Button) this.findViewById(R.id.btnSendMessage); btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { LooperThread.sHandler.sendEmptyMessage(MESSAGE_WXB_1); } }); } //定义子线程 static class LooperThread extends Thread { public static Handler sHandler = null; public void run() { //创建消息循环 Looper.prepare(); sHandler = new Handler() { public void handleMessage(Message msg) { switch(msg.what){ case MESSAGE_WXB_1: mHandler.sendEmptyMessage(MESSAGE_WXB_1); break; } } }; //开启消息循环 Looper.loop(); } } }
AsyncTask:
AsyncTask使用时必须作为基类被扩展,子类至少重载一个方法doInBackground,另一个方法onPostExecute也经常被重载,代码如下:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> { protected Long doInBackground(URL... urls) { int count = urls.length; long totalSize = 0; for (int i = 0; i < count; i++) { totalSize += Downloader.downloadFile(urls[i]); publishProgress((int) ((i / (float) count) * 100)); // Escape early if cancel() is called if (isCancelled()) break; } return totalSize; } protected void onProgressUpdate(Integer... progress) { setProgressPercent(progress[0]); } protected void onPostExecute(Long result) { showDialog("Downloaded " + result + " bytes"); } }
AsyncTask含有三个泛型参数:
Params, 异步任务执行所需的参数类型;
Progress, 异步任务执行进度的类型;
Result, 异步任务执行结果的类型。
这三个参数不必全部使用,不使用的参数置为Void即可,例如:
private class MyTask extends AsyncTask<Void, Void, Void> { ... }
AsyncTask的四个重要方法:
当一个异步任务被执行时,要经历四步:
onPreExecute(),在UI线程中执行,它会在异步任务开始前执行,一般用来设置任务参数;
doInBackground, 最重要的方法,在子线程中执行(事实上,只有它在子线程中执行,其他方法都在UI线程中执行)。当onPreExecute结束后,本方法立刻执行,它用来进行后台的耗时计算,异步任务的参数会被传给它,执行完成的结果会被送给第四步;执行途中,它还可以调用publishProgress 方法来通知UI线程当前执行的进度;
onProgressUpdate, 当publishProgress 被调用后,它在UI线程中执行,刷新任务进度,一般用来刷新进度条等UI部件;
onPostExecute, 当后台的异步任务完成后,它会在UI线程中被调用,并获取异步任务执行完成的结果。