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

作者:Joah 时间:2021-10-27 16:50:36 

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()的区别:https://www.jb51.net/article/120624.htm

4. 内存泄漏

https://www.jb51.net/article/120627.htm

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实现线程之间的通信下载文件动态更新进度条网站的支持!

来源:http://www.cnblogs.com/joahyau/archive/2017/08/07/7301546.html

标签:android,handler
0
投稿

猜你喜欢

  • Android IPC机制绑定Service实现本地通信

    2023-10-08 15:25:40
  • 一文看懂C#中List的扩容机制

    2022-11-04 22:12:01
  • 使用springboot打包成zip部署,并实现优雅停机

    2021-08-04 20:45:01
  • 通过实例解析spring环绕通知原理及用法

    2022-12-26 23:33:20
  • Android如何自定义EditText下划线?

    2022-06-27 10:49:07
  • Java Idea高效率配置技巧实例解析

    2023-06-05 13:24:42
  • java 打造阻塞式线程池的实例详解

    2022-09-13 09:50:33
  • 使用Http Head方法获取文件长度的实现方法详解

    2023-04-05 01:50:37
  • Android实现Window弹窗效果

    2022-12-07 21:48:16
  • C#使用System.Net邮件发送功能踩过的坑

    2022-09-09 18:16:11
  • C语言文件操作函数大全(超详细)

    2023-07-15 06:20:42
  • java Spring Boot 配置redis pom文件操作

    2022-01-25 20:57:13
  • springboot整合mybatisplus的方法详解

    2023-05-20 18:35:05
  • Java并发编程之ReentrantLock可重入锁的实例代码

    2021-12-10 06:05:50
  • java实现查找替换功能

    2021-12-15 00:46:50
  • Qt串口通信开发之QSerialPort模块简单使用方法与实例

    2023-03-23 03:25:45
  • Java8中接口的新特性使用指南

    2023-01-21 15:19:26
  • 2022编程语言需求排名出炉:第一不是Python,也不是Java

    2023-10-11 19:09:17
  • Android 调用系统相机拍摄获取照片的两种方法实现实例

    2022-01-19 21:22:23
  • Spring中的事务隔离级别和传播行为

    2022-07-21 18:18:24
  • asp之家 软件编程 m.aspxhome.com