Android开发之Handler机制及AsyncTask的使用
来源:互联网 发布:如何将压缩的js还原 编辑:程序博客网 时间:2024/06/16 12:35
开启线程的两种方式:
1,新建一个类继承Thread,然后重写父类的run()方法,最后调用它的start()方法。
2,使用继承的方式耦合性有点高,更多的时候会选择使用实现Runnable接口的方式来定义一个线程。
在子线程中更新UI
如果想要更新应用程序的UI元素,则必须在主线程中进行,否则会出现异常。
1,使用handler异步消息处理子线程更新UI的使用方法。
public class MainActivity extends AppCompatActivity { public static final int UPDATE_TEXT = 1; private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case UPDATE_TEXT: //在这里可以进行UI操作 break; default: break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button mUpdate = (Button)findViewById(R.id.btn_get); mUpdate.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new Thread(new Runnable() { @Override public void run() { Message message = new Message(); message.what = UPDATE_TEXT; handler.sendMessage(message); //将message对象发送出去。 } }).start(); } }); }}
解析异步消息处理机制:
Android中异步消息处理主要由4个部分组成:Message、Handler、MessageQueue、Looper。
1,Message
Message是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间交换数据。
2,Handler
Handler主要是用于发送和处理消息的。发送消息一般是使用Handler的sendMessage()方法,而发出的消息经过一系列的处理后,最后会传递到Handler的handleMessage()方法中。
3,MessageQueue
MessageQueue主要用于存放所有通过handler发送的消息,这部分消息会一直存在于消息队列中,等待被处理。每一个线程中只会有一个MessageQueue对象。
4,Looper
Looper是每个线程中的MessageQueue的管家,调用Looper的loop()方法后,就会进入到一个无线循环中,然后每当发现MessageQueue中存在一条消息,就会将它取出,并传递到Handlerde 的handleMessage()方法中。
整个流程:
首先需要在主线程当中创建一个Handler对象,并重写handleMessage()方法。然后当子线程中需要进行UI操作时,就创建一个Message对象,并通过Handler将这条消息发送出去。之后这条消息会被添加到MessageQueue的队列中等待被处理,而Looper则会一直尝试从MessageQueue中取出待处理的消息,最后分发回Handler的handleMessage()方法中。
2,runOnUiThread()也可以在子线程更新UI,其实也是一个异步消息处理机制的接口封装。
3,使用AsyncTask
诀窍:在doInBackground()方法中执行具体的耗时任务,在onProgressUpdate()方法中进行UI操作,在onPostExecute()方法中执行一些任务的收尾工作。
package com.gyq.servicebestpractice;import android.os.AsyncTask;import android.os.Environment;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.io.RandomAccessFile;import okhttp3.OkHttpClient;import okhttp3.Request;import okhttp3.Response;/** * ${DESC} * author: gyq * create at 2016/12/27 16:21 */public class DownloadTask extends AsyncTask<String,Integer,Integer> { public static final int TYPE_SUCCESS = 0; public static final int TYPE_FAILED = 1; public static final int TYPE_PAUSED = 2; public static final int TYPE_CANCELED = 3; private DownloadListener listener; private boolean isCanceled = false; private boolean isPaused = false; private int lastProgress; public DownloadTask(DownloadListener listener) { this.listener = listener; } @Override protected Integer doInBackground(String... params) { InputStream is = null; RandomAccessFile savedFile = null; File file = null; try { long downloadedLength = 0; //记录已下载的文件长度 String downloadUrl = params[0]; String fileName = downloadUrl.substring(downloadUrl.lastIndexOf("/")); String directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath(); file = new File(directory + fileName); if (file.exists()) { downloadedLength = file.length(); } long contentLength = getContentLength(downloadUrl); if (contentLength == 0) { return TYPE_FAILED; }else if (contentLength == downloadedLength) { //已下载字节和文件总字节相等,说明已经下载完成了 return TYPE_SUCCESS; } OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() //断点下载,指定从哪个字节开始下载 .addHeader("RANGE","bytes = " + downloadedLength + "-") .url(downloadUrl) .build(); Response response = client.newCall(request).execute(); if (response != null) { is = response.body().byteStream(); savedFile = new RandomAccessFile(file,"rw"); savedFile.seek(downloadedLength); byte[] b = new byte[1024]; int total = 0; int len; while ((len = is.read(b)) != -1) { if (isCanceled) { return TYPE_CANCELED; }else if (isPaused) { return TYPE_PAUSED; }else { total += len; savedFile.write(b,0,len); //计算已下载的百分比 int progress = (int)((total + downloadedLength) * 100 / contentLength); publishProgress(progress); } } response.body().close(); return TYPE_SUCCESS; } }catch (Exception e) { e.printStackTrace(); }finally { try { if (is != null) { is.close(); } if (savedFile != null) { savedFile.close(); } if (isCanceled && file != null) { file.delete(); } }catch (Exception e) { e.printStackTrace(); } } return TYPE_FAILED; } @Override protected void onProgressUpdate(Integer... values) { int progress = values[0]; if (progress > lastProgress) { listener.onProgress(progress); lastProgress = progress; } } @Override protected void onPostExecute(Integer status) { switch (status) { case TYPE_SUCCESS : listener.onSuccess(); break; case TYPE_FAILED : listener.onFailed(); break; case TYPE_PAUSED : listener.onPaused(); break; case TYPE_CANCELED : listener.onCanceled(); break; default: break; } } public void pauseDownload() { isPaused = true; } public void cancelDownload() { isCanceled = true; } private long getContentLength(String downloadUrl) throws IOException { OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url(downloadUrl) .build(); Response response = client.newCall(request).execute(); if (response != null && response.isSuccessful()) { long contentLength = response.body().contentLength(); response.close(); return contentLength; } return 0; }}
如果想启动这个任务,只需编写如下代码:
new DownloadTask().execute();
- Android开发之Handler机制及AsyncTask的使用
- Android开发之AsyncTask机制及使用细节
- Handler机制和AsyncTask机制的使用
- android开发之源码级分析(系统启动流程 & Handler消息机制 & AsyncTask机制)
- 【Android开发】线程间通讯机制(基础篇)——Handler、Runnable、HandlerThread、AsyncTask的使用
- 【Android开发】线程间通讯机制(基础篇)——Handler、Runnable、HandlerThread、AsyncTask的使用
- Android开发之AsyncTask的使用
- Android开发之AsyncTask的使用
- Android多线程开发之AsyncTask的使用
- Android之Handler与AsyncTask的区别
- Android基础 AsyncTask、Handler的使用
- Android开发之Handler的使用
- Android开发基础之Handler的使用
- Android中实现异步任务机制的方式:Handler、AsyncTask
- android中的消息机制--浅谈Handler的原理及使用
- Android的内存机制及AsyncTask
- android开发 AsyncTask的使用
- Android开发之Handler消息传递机制
- javascript 3行代码的分页算法(求起始页和结束页)
- (二十四)解释器模式详解
- python 编码问题
- Struts2标签学习
- Altium Designer
- Android开发之Handler机制及AsyncTask的使用
- 面向对象跟面向过程的区别
- JS JSONP跨域请求实例详解
- (转)程序中的@Override是什么意思?
- 树莓派开机自动运行某程序.md
- [Redis on Java]Redis Jedis缓冲池配置总结(补充中)
- ubuntu 13.10 64bit装BeyondCompare
- 你好,2017----积累收获和展望
- Android中关于微信支付和支付宝支付