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系统支持的颜色是由4个值组成的,前3个为RGB,也就是我们常说的三原色(红、绿、蓝),最后一个值是A,也就是Alpha。这4个
- 1.POM文件导入Springboot整合websocket的依赖 <depen
- feign对象传参和普通传参及遇到的坑对象传参使用@RequestBody来指定传参对象@RequestMapping(value = &q
- FastJson是阿里开源的一个高性能的JSON框架,FastJson数据处理速度快,无论序列化(把JavaBean对象转化成Json格式的
- 这一篇主要是用来介绍关于C#中的XML序列化的问题,这个相信大家一定会经常使用它,特别是在WPF中,有时候我们需要将我们后台的数据保存在数据
- 我们在应用中经常看到一些选择开关状态的配置文件,做项目的时候用的是android的Switch控件,但是感觉好丑的样子子个人认为还是自定义的
- 一、流程图二、Token1、token是一种客户端认证机制,是一个经过加密的字符串,安全性强,支持跨域2、用户第一次登录,服务器通过数据库校
- 本文实例为大家分享了java数独游戏的具体代码,供大家参考,具体内容如下自己写的数独游戏,共9关,代码如下:1、DoShudu类用于产生数独
- 本文实例讲述了C#图像伪彩色处理方法。分享给大家供大家参考。具体如下://灰度图转伪彩色图像函数public Bitmap PGrayToC
- map中相同的key保存多个value值在java中,Map集合中只能保存一个相同的key,如果再添加相同的key,则之后添加的key的值会
- 根据数据库表名生成实体类公司用的jpa,没有用mybatis。所以也没有用mybatis自动生成。但有些数据库表字段太多,就想着一劳永逸了,
- 1. JNI简介JNI是Java Native Interface的英文缩写,意为Java本地接口。问题来源:由于Java编写底层的应用较难
- XML中的扫描过程<?xml version="1.0" encoding="utf-8" ?
- 本文实例讲述了C#使用StopWatch获取程序毫秒级执行时间的方法。分享给大家供大家参考。具体分析如下:这个比时间通过DateTime在程
- 本篇主要总结下Spring容器在初始化实例前后,提供的一些回调方法和可扩展点。利用这些方法和扩展点,可以实现在Spring初始化实例前后做一
- 本文实例为大家分享了C#实现图表中鼠标移动并显示数据的具体代码,供大家参考,具体内容如下效果图:1.首先在页面上添加一个label控件并 默
- 本文实例讲述了Android编程基于距离传感器控制手机屏幕熄灭的方法。分享给大家供大家参考,具体如下:在现实生活中,打电话的时候手机挨着自己
- Druid动态数据源配置 主要是继承AbstractRoutingDataSource再通过AOP来实现动态数据源切换.下面给大家介绍Dru
- 一、简述mybatis驼峰式命名规则自动转换:使用前提:数据库表设计按照规范“字段名中各单词使用下划线"_"划分”;使用
- 前言前段时间准备做一个视频,最后需要添加字幕,手动添加太麻烦了就想在网上找一个能自动提取字幕的软件或服务,确实是找到了,但是免费版基本上都有