Handler实现线程之间的通信下载文件动态更新进度条
1. 原理
每一个线程对应一个消息队列messagequeue,实现线程之间的通信,可通过handler对象将数据装进message中,再将消息加入消息队列,而后线程会依次处理消息队列中的消息。
2. message
初始化:一般使用message.obtain()方法获取一个消息对象,该方法会检查message对象池中是否存在可重复利用的对象,若无,才会new一个新对象。
what:相当于message的标识符,区别于其它消息。
arg1、arg2:int类型,可传递整数。
obj:object类型,可传递任意对象。
3. 发送消息
在子线程中可调用主线程的handler.sendmessage(msg)
进行发送消息,经过一系列方法调用,会触发handler的handlemessage方法,从而进行消息处理。
发送消息的主要方法:
handler.sendmessage(message msg); handler.sendmessageattime(message msg, int time); handler.sendmessagedelayed(message msg, int time);
sendmessageattime()
和sendmessagedelayed()
区别在于前者是在指定时间发送消息,可配合systemclock.uptimemillis()
使用;而后者则是延时发送消息。
除了sendmessage()方法以外,还可以通过post()方法发送消息:
handler.post(runnable r); handler.postdelayed(runnable r, int time);
sendmessage()与post()的区别:
4. 内存泄漏
5. 通过handler对象实现下载文件动态更新进度条
androidmanifest加入权限声明:
<uses-permission android:name="android.permission.internet" /> <uses-permission android:name="android.permission.write_external_storage" /> <uses-permission android:name="android.permission.read_external_storage" />
布局:
<?xml version="1.0" encoding="utf-8"?> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="10dp" tools:context="com.studying.network.downloadactivity"> <progressbar android:id="@+id/progress_bar" style="?android:progressbarstylehorizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:max="100" /> <button android:id="@+id/download" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margintop="10dp" android:text="@string/download" /> </linearlayout>
activity:
public class downloadactivity extends activity { private static final int download_message_code = 100001; private static final int download_message_fail_code = 100002; private static final string app_url = "http://clfile.imooc.com/class/assist/119/1328281/android%20studio%20教辅%20.pdf"; private myhandler mhandler; private progressbar mprogressbar; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_download); findviewbyid(r.id.download).setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { //开启子线程 new thread(new runnable() { @override public void run() { download(app_url); } }).start(); } }); mprogressbar = (progressbar) findviewbyid(r.id.progress_bar); mhandler = new myhandler(this); } private void download(string appurl) { try { url url = new url(appurl); urlconnection conn = url.openconnection(); inputstream in = conn.getinputstream(); int contentlength = conn.getcontentlength();//获取文件总大小 string downloadpath = environment.getexternalstoragedirectory() + file.separator + "imooc" + file.separator; file file = new file(downloadpath); if (!file.exists()) { file.mkdir(); } string filename = downloadpath + "test.pdf"; file apkfile = new file(filename); if (apkfile.exists()) { apkfile.delete(); } int downloadsize = 0;//记录已经下载的大小 byte[] bytes = new byte[1024]; int length = 0; outputstream out = new fileoutputstream(filename); while ((length = in.read(bytes)) != -1) { out.write(bytes, 0, length); downloadsize += length; message msg = message.obtain(); msg.obj = downloadsize / contentlength * 100;//progress的值为0到100,因此得到的百分数要乘以100 msg.what = download_message_code; mhandler.sendmessage(msg); } in.close(); out.close(); } catch (ioexception e) { notifydownloadfailed(); e.printstacktrace(); } } private void notifydownloadfailed() { message msg = message.obtain(); msg.what = download_message_fail_code; mhandler.sendmessage(msg); } private static class myhandler extends handler{ private weakreference<downloadactivity> weakreference; myhandler(downloadactivity activity) { this.weakreference = new weakreference<>(activity);//以弱引用的形式传递activity,避免内存泄漏 } @override public void handlemessage(message msg) { super.handlemessage(msg); downloadactivity activity = weakreference.get(); //消息处理 switch (msg.what) { case download_message_code: activity.mprogressbar.setprogress((integer) msg.obj); break; case download_message_fail_code: toast.maketext(activity, "下载失败!", toast.length_short).show(); break; } } } }
总结
以上所述是小编给大家介绍的handler实现线程之间的通信下载文件动态更新进度条,希望对大家有所帮助
上一篇: 百度影音自动更新功能怎么关闭?
下一篇: JS实现带阴历的日历功能详解