Android類FileDownloadList分析
先上代碼,再來分析
public class FileDownloadList {
/**上下文*/
private Context mContext;
/**請求對象*/
private BaseRequestLims fileRequest = null;
/**進度條對話框*/
private AlertDialog progressDialog = null;
/**進度條控件變量*/
private ProgressBar mProgress;
/**百分比顯示控件*/
private TextView mProgressPercent;
private File localFile = null;
/**接收HttpHelper中獲取到文件大小后發(fā)送的廣播,確定文件大小*/
private DownLoadReceiver receiver;
/**文件大小*/
private long fileLength = -1L;
/**是否已注冊廣播標志*/
private boolean castFlag = false;
/**是否顯示進度條標志*/
private boolean showDialog = false;
/**文件下載完的回調(diào)接口*/
private Runnable mCallback = null;
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
int tempSize = (int)localFile.length();
if(tempSize < fileLength){
//文件下載中
if(showDialog){
//顯示了進度條的情況下,更新進度條
int progress = (int)((Double.valueOf(tempSize) / Double.valueOf(fileLength)) * 100);
mProgress.setProgress(tempSize);
mProgressPercent.setText(progress + "%");
}
}else{
//下載文件完畢
if(castFlag){//如已注冊廣播,注銷廣播
mContext.unregisterReceiver(receiver);
castFlag = false;
}
if(showDialog){
mProgress.setProgress((int)fileLength);
mProgressPercent.setText("100%");
progressDialog.dismiss();
}
if(mCallback != null){
try{
Thread.sleep(500);
mCallback.run();
}catch (Exception e) {
e.printStackTrace();
}
}
}
}
};
/**
* 構(gòu)造器
* @param activity
*/
/**
* 構(gòu)造器
* @param activity
* @param showDialog 顯示進度條標志
*/
public FileDownloadList(Context context, boolean showDialog){
mContext = context;
this.showDialog = showDialog;
fileRequest = new BaseRequestLims(context,ClientServiceType.FILE_DOWN);
fileRequest.setMethodType(BaseRequestLims.METHOD_TYPE_POST);
fileRequest.setContext(mContext);
}
public BaseRequestLims getFileRequest(){
return fileRequest;
}
/**
* 通過關聯(lián)類型來下載文件
* @param fileName 文件名稱或文件在服務器上的相對路徑加名稱
* @param saveDir 保存在本地的文件目錄
* @param saveName 保存在本地的文件名稱
* @param gllx 關聯(lián)類型
* @param callback 下載后的處理線程
*/
public void downloadFile(String fileName, String saveDir, String saveName, Runnable callback){
if(callback != null){
mCallback = callback;
}
File saveDirFile = new File(saveDir);
//judge the save dir path exist or not
if(!saveDirFile.exists()){
saveDirFile.mkdirs();
}
localFile = new File(saveDir,saveName);
if(localFile.isDirectory()){
new AlertDialog.Builder(mContext).setTitle("提示").setMessage("the save file is directory").show();
return;
}
if(fileRequest.getServiceType()==null){
fileRequest.setServiceType(ClientServiceType.FILE_DOWN);
}
fileRequest.addParameter("fpath", fileName);
fileRequest.addParameter("fname", saveName);
fileRequest.setStreamPath(localFile.getAbsolutePath());
fileRequest.setStream(true);
if(localFile.exists()){
if(localFile.length() == 0){
invokeFile(fileRequest);
}else{
//文件存在直接打開
if(showDialog)
buildProgressDialog().show();
mHandler.sendMessage(mHandler.obtainMessage());
}
}else{
invokeFile(fileRequest);
}
}
/**
* 進入文件下載子線程
* @param request
*/
private void invokeFile(final BaseRequestLims request){
try{
if(showDialog){
buildProgressDialog().show();
}
receiver = new DownLoadReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("SAVE_DOWNLOAD_FILE");
mContext.registerReceiver(receiver, filter);
castFlag = true;
//下載的子線程
new Thread(){
@Override
public void run() {
super.run();
HttpHelper.invoke(request);
}
}.start();
}catch (Exception e) {
e.printStackTrace();
}
}
/**
* 創(chuàng)建進度對話框
* @return
*/
private AlertDialog buildProgressDialog(){
AlertDialog.Builder builder = new Builder(mContext);
builder.setTitle("正在下載文件,請稍候...");
RelativeLayout container = new RelativeLayout(mContext);
mProgress = new ProgressBar(mContext);
mProgress.setId("progress".hashCode());
BeanUtils.setFieldValue(mProgress, "mOnlyIndeterminate", Boolean.valueOf(false));
mProgress.setIndeterminate(false);
LayerDrawable layerDrawable = (LayerDrawable)mContext.getResources().getDrawable(android.R.drawable.progress_horizontal);
ClipDrawable clipDrawable = (ClipDrawable)layerDrawable.getDrawable(2);
clipDrawable.setColorFilter(Color.parseColor("#32B5E5"), Mode.SRC_IN);
mProgress.setProgressDrawable(layerDrawable);
mProgress.setPadding(0, 0, 0, 0);
mProgress.setIndeterminateDrawable(
mContext.getResources().getDrawable(android.R.drawable.progress_indeterminate_horizontal));
mProgressPercent = new TextView(mContext);
mProgressPercent.setId("percent".hashCode());
mProgressPercent.setText("0%");
mProgressPercent.setTextSize(18);
int containerPadding = DimensionUtils.dip2Px(mContext, 10);
container.setPadding(containerPadding, containerPadding, containerPadding, containerPadding);
LayoutParams progressLayoutParams = new LayoutParams(
LayoutParams.MATCH_PARENT, DimensionUtils.dip2Px(mContext, 4));
progressLayoutParams.addRule(RelativeLayout.CENTER_VERTICAL);
progressLayoutParams.addRule(RelativeLayout.LEFT_OF, mProgressPercent.getId());
mProgress.setLayoutParams(progressLayoutParams);
LayoutParams percentLayoutParams = new LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
percentLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
percentLayoutParams.addRule(RelativeLayout.CENTER_VERTICAL);
mProgressPercent.setLayoutParams(percentLayoutParams);
container.addView(mProgressPercent);
container.addView(mProgress);
builder.setView(container);
builder.setNegativeButton("取消", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
progressDialog = builder.create();
return progressDialog;
}
class DownLoadReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
//顯示進度條
fileLength = intent.getLongExtra("FILE_LENGTH", -1);
if(showDialog){
mProgress.setMax((int)fileLength);
}
//更新進度條的線程
new Thread(){
@Override
public void run() {
super.run();
while(true){
try{
Thread.sleep(500);
}catch (Exception e) {
e.printStackTrace();
}
mHandler.sendMessage(mHandler.obtainMessage());
//獲取下載文件的大小
int loadedSize = (int)localFile.length();
if(loadedSize >= fileLength){
break;
}
}
}
}.start();
}
}
public DownLoadReceiver getReciver()
{
return receiver;
}
}
它的邏輯:
創(chuàng)建一個FileDownloadList對象后,就可以直接使用該下述方法來實現(xiàn)下載功能。
downloadFile(String fileName, String saveDir, String saveName, Runnable callback)
在實現(xiàn)上是這么個意思:
1.在當前上下文,開啟下載線程。當獲取到要下載的文件的大小時,發(fā)送一個廣播過來(這部分沒有展示在上述代碼中)。
2.在當前上下文中,注冊一個廣播監(jiān)聽器,監(jiān)聽廣播標識為SAVE_DOWNLOAD_FILE的廣播。首次監(jiān)聽到發(fā)出來的廣播后,首次發(fā)送過來的廣播,包含了要下載的文件的大小信息,然后就每隔5毫秒檢測本地文件的大小,直到本地文件的大小(loadedSize)大于等于要下載的文件(fileLength)大小時,退出該循環(huán)。
在不斷檢測的過程中,通過mHandler.sendMessage(mHandler.obtainMessage()); ,讓UI線程更新進度條。
下載線程,會不斷將服務器返回的數(shù)據(jù)流,寫到本地文件中,所以,本地文件的大小會不斷變化,直到,它的大小跟要下載的文件的大小相等時,就退出這個不斷檢測本地文件大小的線程。
其它沒有在上述代碼中表現(xiàn)出來的內(nèi)容(在其它部分的代碼中):
1.在invokeFile( final BaseRequestLims request)方法中,開了一個如下的下載線程.該下載線程,會將服務器返回的文件流,寫到本地文件(localFile)中;然后,它還會發(fā)送一個標識為SAVE_DOWNLOAD廣播,包含的信息有要下載文件的文件大小fileLength。
//下載的子線程
new Thread(){
@Override
public void run() {
super.run();
HttpHelper.invoke(request);
}
}.start();
上述代碼存在的問題:
1.上下文,使用的是某個Activity,如果發(fā)生系統(tǒng)調(diào)用了該Activity的onDestroy()時,下載線程還沒有完成,也就意味著,loadedSize的大小還是小于fileLength。從而,那個不斷檢測本地文件大小的線程就一直在執(zhí)行著。
即是檢測本地文件大小的線程和下載線程還在執(zhí)行著:
檢測本地文件大小的線程:
new Thread(){
@Override
public void run() {
super.run();
while(true){
try{
Thread.sleep(500);
}catch (Exception e) {
e.printStackTrace();
}
mHandler.sendMessage(mHandler.obtainMessage());
//獲取下載文件的大小
int loadedSize = (int)localFile.length();
if(loadedSize >= fileLength){
break;
}
}
}
}.start();
下載線程:
new Thread(){
@Override
public void run() {
super.run();
HttpHelper.invoke(request);
}
}.start();
那么,會出現(xiàn)什么問題呢?
1).我可以確定的就是,mContext會出現(xiàn)泄漏。
2). DownLoadReceiver不能正常被取消注冊。
分析,待續(xù)。
- Android學習筆記-保存文件(Saving Files)
- android實現(xiàn)Uri獲取真實路徑轉(zhuǎn)換成File的方法
- android開發(fā)教程之獲取power_profile.xml文件的方法(android運行時能耗值)
- Android編程中FileOutputStream與openFileOutput()的區(qū)別分析
- Android 數(shù)據(jù)存儲之 FileInputStream 工具類及FileInputStream類的使用
- Android采用File形式保存與讀取數(shù)據(jù)的方法
- Android編程實現(xiàn)文件瀏覽功能的方法【類似于FileDialog的功能】
- Android數(shù)據(jù)持久化之Preferences機制詳解
- 詳解Android開發(fā)數(shù)據(jù)持久化之文件存儲(附源碼)
- Android仿QQ好友列表分組實現(xiàn)增刪改及持久化
- Android持久化技術(shù)之SharedPreferences存儲實例詳解
- Android持久化技術(shù)之文件的讀取與寫入實例詳解
- Android數(shù)據(jù)持久化之File機制分析
相關文章
Android 消息機制以及handler的內(nèi)存泄露
這篇文章主要介紹了Android 消息機制以及handler的內(nèi)存泄露的相關資料,需要的朋友可以參考下2016-09-09
android教程之使用popupwindow創(chuàng)建菜單示例
這篇文章主要介紹了android使用popupwindow創(chuàng)建菜單的示例,需要的朋友可以參考下2014-02-02
Android實時獲取攝像頭畫面?zhèn)鬏斨罰C端思路詳解
這篇文章主要介紹了Android實時獲取攝像頭畫面?zhèn)鬏斨罰C端思路詳解,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-07-07
Android studio listview實現(xiàn)列表數(shù)據(jù)顯示 數(shù)據(jù)循環(huán)顯示效果
這篇文章主要介紹了Android studio listview實現(xiàn)列表數(shù)據(jù)顯示 數(shù)據(jù)循環(huán)顯示功能,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-04-04
Android開發(fā)實現(xiàn)SubMenu選項菜單和子菜單示例
這篇文章主要介紹了Android開發(fā)實現(xiàn)SubMenu選項菜單和子菜單,結(jié)合實例形式分析了Android開發(fā)中SubMenu選項菜單和子菜單的功能、配置、布局等相關操作技巧,需要的朋友可以參考下2019-03-03
Android數(shù)據(jù)庫SD卡創(chuàng)建和圖片存取操作
這篇文章主要介紹了Android數(shù)據(jù)庫SD卡創(chuàng)建和圖片存取操作的相關資料,需要的朋友可以參考下2017-04-04
android ItemTouchHelper實現(xiàn)可拖拽和側(cè)滑的列表的示例代碼
本篇文章主要介紹了ItemTouchHelper實現(xiàn)可拖拽和側(cè)滑的列表的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-02-02
快速解決Android7.0下沉浸式狀態(tài)欄變灰的問題
下面小編就為大家分享一篇快速解決Android7.0下沉浸式狀態(tài)欄變灰的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-01-01

