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()的区别:https://www.zalou.cn/article/120624.htm
4. 内存泄漏
https://www.zalou.cn/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实现线程之间的通信下载文件动态更新进度条,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对ZaLou.Cn网站的支持!
- Web黑盒渗透思路之猜想
- ZZCMS v8.2 最新版SQL注入漏洞
- 一款轻量级Web漏洞教学演示系统(DSVW)
- 使用Burpsuite代理和pypcap抓包进行抢红包的尝试
- 基于WAVSEP的靶场搭建指南
- 【干货】大数据量下,58同城mysql实践!
- 如何预先处理电影评论数据以进行情感分析
- 如何在Python中从零开始实现随机森林
- 教程从头开始在Python中实现k最近邻居
- 建立安全的 AI
- Python NLTK 自然语言处理入门与例程
- 漏洞预警 | Apache Struts2 曝任意代码执行漏洞 (S2-045,CVE-2017-5638)
- 详解OSSIM-OSSEC WIN 4771案例
- JSShell:一个基于python的交互式Shell
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 图像处理笔记(6)---- OpenCV waitKey函数
- SpringBoot整合Quartz作为调度中心完整实用例子
- SpringBoot整合SpringSecurity简单实现登入登出从零搭建
- SpringBoot整合SpringBatch实用简例
- 解决JPA懒加载典型的N+1问题-注解@NamedEntityGraph
- 基于Shiro,JWT实现微信小程序登录完整例子
- Spring Cloud Eureka 总结
- Spring Cloud Feign 总结
- 掘金15W沸点简单分析(一)
- SpringBoot整合Shiro实现基于角色的权限访问控制(RBAC)系统简单设计从零搭建
- 基于AOP和ThreadLocal实现日志记录
- 搭建prometheus+grafana监控SpringBoot应用入门
- 掘金15W沸点简单分析(二)
- 老生常谈SpringAop日志收集与处理做的工具包
- 线程间通信wait---notify