當前位置:
首頁 > 知識 > Handler實現線程之間的通信-下載文件動態更新進度條

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);

4. 內存泄漏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"
stylex="?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;
}
}
}
}

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 達人科技 的精彩文章:

vue+mockjs 模擬數據,實現前後端分離開發
ReactiveSwift源碼解析(十)Lifetime代碼實現
一份關於webpack2和模塊打包的新手指南
Openresty使用Thrift安裝步驟

TAG:達人科技 |

您可能感興趣

Unity發布WebGL時如何修改/刪除默認的Logo和載入進度條
cocos2dx實現載入頁loading頁,載入進度條和載入字樣(附代碼)
Kickstarter升級Hardware Studio:讓投資者知道眾籌項目發展進度
Android系統視頻最新進度:音頻更新12節
已投項目進度更新—OPEN chain技術路線圖更新
Kanye West 揭露 Kid Cudi、NAS 與個人的「新專輯進度表」
對產業化進度不滿,Facebook AI團隊調整背後的路線之爭
vivo X9 X9Splus系統空間損壞內存不足下載進度
Switch安卓模擬器MonoNX發布 進度飛快!
你的《荒野大鏢客Online》Beta進度應該不會被R星重置
10nm晶元進度緩慢 蘋果新MacBook Pro將小幅更新
Switch破解進度迅速 已能運行Windows95
英特爾IceLake進度太慢,谷歌ChromeOS將不支持
《血污:夜之儀式》取消Mac/Linux版本 開發進度良好
谷歌對Intel 10nm進度不滿:Chrome OS將不支持Ice Lake
Photoshop繪製立體感十足的進度條圖標
谷歌對Intel 10nm進度不滿,或將停用Ice Lake
華為Android Pie進度積極 9款機型招募內測
《血跡》取消MAC/Linux版 開發進度良好
B社宣布《輻射76》將登陸Bethesda.net 測試版進度可繼承