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()的区别:http://blog.csdn.net/u013168615/article/details/47024073
4. 内存泄漏
http://www.cnblogs.com/xujian2014/p/5025650.html
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实现线程之间的通信-下载文件动态更新进度条的更多相关文章
- AsyncTask用法解析-下载文件动态更新进度条
1. 泛型 AysncTask<Params, Progress, Result> Params:启动任务时传入的参数,通过调用asyncTask.execute(param)方法传入. ...
- 通过HttpUrlConnection下载文件并显示进度条
实现效果: 核心下载块: int count = 0; URL url = new URL("http://hezuo.downxunlei.com/xunlei_hezuo/thunder ...
- WPF多线程下载文件,有进度条
//打开对话框选择文件 private void OpenDialogBox_Click(object sender, RoutedEventArgs e) { ...
- 使用libcurl开源库和Duilib做的下载文件并显示进度条的小工具
转载:http://blog.csdn.net/mfcing/article/details/43603525 转载:http://blog.csdn.net/infoworld/article/de ...
- C# Winform下载文件并显示进度条
private void btnDown_Click(object sender, EventArgs e) { DownloadFile("http://localhost:1928/We ...
- Winform下载文件并显示进度条
本来是要研究怎样判断下载完成,结果找到这个方法,可以在这个方法完成之后提示下载完成. 代码如下: using System; using System.Collections.Generic; usi ...
- iOS边练边学--多线程介绍、NSThread的简单实用、线程安全以及线程之间的通信
一.iOS中的多线程 多线程的原理(之前多线程这块没好好学,之前对多线程的理解也是错误的,这里更正,好好学习这块) iOS中多线程的实现方案有以下几种 二.NSThread线程类的简单实用(直接上代码 ...
- Android笔记(三十一)Android中线程之间的通信(三)子线程给主线程发送消息
先看简单示例:点击按钮,2s之后,TextView改变内容. package cn.lixyz.handlertest; import android.app.Activity; import and ...
- Thread线程源码解析,Java线程的状态,线程之间的通信
线程的基本概念 什么是线程 现代操作系统在运行一个程序的时候,会为其创建一个进程.例如,启动一个Java程序,操作系统就会创建一个Java进程.线代操作系统调度的最小单位是线程.也叫做轻量级进程.在一 ...
随机推荐
- 【CC2530入门教程-04】CC2530的定时/计数器原理与应用
第4课 CC2530的定时/计数器原理与应用 广东职业技术学院 欧浩源 一.定时/技术器的基本原理 定时/计数器,是一种能够对内部时钟信号或外部输入信号进行计数,当计数值达到设定要求时,向CPU提 ...
- 如何用JavaScript复制到剪贴板
<!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="UTF-8& ...
- MySQL访问控制实现原理
MySQL访问控制实现原理 MySQL 访问控制实际上由两个功能模块共同组成,从第一篇的第二章架构组成中可以看到,一个是负责 “看守 MySQL 大门”的用户管理模块,另一个就是负责监控来访者每一个动 ...
- DOCKER 从入门到放弃(二)
搜索镜像 从docker官方镜像仓库搜索镜像 docker search [OPTIONS] TERM OPTIONS: --automated :只显示自动创建的镜像,默认值为fasle --fil ...
- 关于Latex中插入Visio图片文字不显示的问题
经过探索,将Visio保存为pdf格式是最完美的解决方式,因为pdf文件保存了所有格式和字体信息. Visio输出pdf时要使其符合PDF/A标准.如果包含Visio的多余信息,就会在一些低版本Lat ...
- 基于vue2.0的网易云音乐 (实时更新)
本人在自学vue,之后想在学习过程中加以实践.由于之前有做过jquery的播放器效果,ui仿照网易云,地址 www.daiwei.org/music 于是就想做vue 的网易云播放器,网上也有类似的项 ...
- 高级Java程序员的技术进阶之路
据不完全统计,截至目前(2017.07)为止,中国Java程序员的数量已经超过了100万.而且,随着IT培训业的持续发展和大量的应届毕业生进入社会,Java程序员面临的竞争压力越来越大.那么,作为 ...
- red hat 6.5 红帽企业Linux.6.5 yum This system is not registered to Red Hat Subscription Management. You can use subscription-manager to register. 解决办法
1.删除redhat原有的yum rpm -aq|grep yum|xargs rpm -e --nodeps 2.下载yum安装文件 wget http://mirrors.163.com/cent ...
- (转载)VB6之鼠标移出事件
转载链接:http://www.ltesting.net/ceshi/ruanjianceshikaifajishu/rjcskfyy/vb/2007/0525/3426.html Windows提供 ...
- Java编程思想总结笔记Chapter 2
本章介绍Java程序的基本组成部分,体会到Java中几乎一切都是对象. 第二章 一切都是对象 目录: 2.1 用引用操纵对象 2.2 必须由你创建所有对象 2.3 永远不需要销毁对象 2.4 创建 ...