Handler實(shí)現(xiàn)線程之間的通信下載文件動(dòng)態(tài)更新進(jìn)度條
1. 原理
每一個(gè)線程對(duì)應(yīng)一個(gè)消息隊(duì)列MessageQueue,實(shí)現(xiàn)線程之間的通信,可通過Handler對(duì)象將數(shù)據(jù)裝進(jìn)Message中,再將消息加入消息隊(duì)列,而后線程會(huì)依次處理消息隊(duì)列中的消息。
2. Message
初始化:一般使用Message.obtain()方法獲取一個(gè)消息對(duì)象,該方法會(huì)檢查Message對(duì)象池中是否存在可重復(fù)利用的對(duì)象,若無,才會(huì)new一個(gè)新對(duì)象。
what:相當(dāng)于Message的標(biāo)識(shí)符,區(qū)別于其它消息。
arg1、arg2:int類型,可傳遞整數(shù)。
obj:object類型,可傳遞任意對(duì)象。
3. 發(fā)送消息
在子線程中可調(diào)用主線程的handler.sendMessage(msg)進(jìn)行發(fā)送消息,經(jīng)過一系列方法調(diào)用,會(huì)觸發(fā)handler的handleMessage方法,從而進(jìn)行消息處理。
發(fā)送消息的主要方法:
handler.sendMessage(Message msg); handler.sendMessageAtTime(Message msg, int time); handler.sendMessageDelayed(Message msg, int time);
sendMessageAtTime()和sendMessageDelayed()區(qū)別在于前者是在指定時(shí)間發(fā)送消息,可配合SystemClock.uptimeMillis()使用;而后者則是延時(shí)發(fā)送消息。
除了SendMessage()方法以外,還可以通過post()方法發(fā)送消息:
handler.post(Runnable r); handler.postDelayed(Runnable r, int time);
sendMessage()與post()的區(qū)別:http://www.dbjr.com.cn/article/120624.htm
4. 內(nèi)存泄漏
http://www.dbjr.com.cn/article/120627.htm
5. 通過Handler對(duì)象實(shí)現(xiàn)下載文件動(dòng)態(tài)更新進(jìn)度條
AndroidManifest加入權(quán)限聲明:
<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;//記錄已經(jīng)下載的大小
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,因此得到的百分?jǐn)?shù)要乘以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,避免內(nèi)存泄漏
}
@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;
}
}
}
}
總結(jié)
以上所述是小編給大家介紹的Handler實(shí)現(xiàn)線程之間的通信下載文件動(dòng)態(tài)更新進(jìn)度條,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
Flutter實(shí)現(xiàn)自定義篩選框的示例代碼
本文主要介紹了Flutter實(shí)現(xiàn)自定義篩選框的示例代碼,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-07-07
新浪微博第三方登錄界面上下拉伸圖片之第三方開源PullToZoomListViewEx(一)
PullZoomView要實(shí)現(xiàn)兩類,一類是典型的Android ListView,另外一類是Android 的scroll view。本文先介紹PullZoomView在ListView上的實(shí)現(xiàn):PullToZoomListViewEx2015-12-12
Android仿網(wǎng)易一元奪寶客戶端下拉加載動(dòng)畫效果(一)
本文通過一個(gè)demo給大家介紹了android仿網(wǎng)易一元奪寶客戶端下拉加載動(dòng)畫效果,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-09-09
android如何默認(rèn)打開小區(qū)廣播具體實(shí)現(xiàn)
小區(qū)廣播的開關(guān),1是打開,0是關(guān)閉;0x00就默認(rèn)關(guān)閉,改成0x01就是默認(rèn)打開,具體修改如下,感興趣的朋友可以參考下哈2013-06-06
Android?Activity通用懸浮可拖拽View封裝的思路詳解
這篇文章主要介紹了Android?Activity通用懸浮可拖拽View封裝,實(shí)現(xiàn)思路是通過封裝通用的基礎(chǔ)懸浮View,繼承通用View,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-07-07
Android中ScrollView嵌套GridView顯示不全解決方法
這篇文章主要介紹了Android中ScrollView嵌套GridView顯示不全解決方法的相關(guān)資料,需要的朋友可以參考下2017-04-04
Android中RecyclerView實(shí)現(xiàn)商品分類功能
這篇文章主要為大家詳細(xì)介紹了Android中RecyclerView實(shí)現(xiàn)商品分類功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02

