欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Handler实现线程之间的通信下载文件动态更新进度条

程序员文章站 2023-11-16 19:45:22
1. 原理 每一个线程对应一个消息队列messagequeue,实现线程之间的通信,可通过handler对象将数据装进message中,再将消息加入消息队列,而后线程会依...

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实现线程之间的通信下载文件动态更新进度条,希望对大家有所帮助