Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android類FileDownloadList分析

Android類FileDownloadList分析

編輯:關於Android編程

先上代碼,再來分析

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中獲取到文件大小後發送的廣播,確定文件大小*/
 private DownLoadReceiver receiver;
 /**文件大小*/
 private long fileLength = -1L;
 /**是否已注冊廣播標志*/
 private boolean castFlag = false;
 /**是否顯示進度條標志*/
 private boolean showDialog = false;
 /**文件下載完的回調接口*/
 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();
     }
    }
   }
  }
 };
 
 /**
  * 構造器
  * @param activity
  */
 
 /**
  * 構造器
  * @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;
 }
 
 /**
  * 通過關聯類型來下載文件
  * @param fileName 文件名稱或文件在服務器上的相對路徑加名稱
  * @param saveDir 保存在本地的文件目錄
  * @param saveName 保存在本地的文件名稱
  * @param gllx 關聯類型
  * @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();
  }
 }
 
 /**
  * 創建進度對話框
  * @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;
 }
}

它的邏輯:

創建一個FileDownloadList對象後,就可以直接使用該下述方法來實現下載功能。

downloadFile(String fileName, String saveDir, String saveName, Runnable callback)

在實現上是這麼個意思:

1.在當前上下文,開啟下載線程。當獲取到要下載的文件的大小時,發送一個廣播過來(這部分沒有展示在上述代碼中)。

2.在當前上下文中,注冊一個廣播監聽器,監聽廣播標識為SAVE_DOWNLOAD_FILE的廣播。首次監聽到發出來的廣播後,首次發送過來的廣播,包含了要下載的文件的大小信息,然後就每隔5毫秒檢測本地文件的大小,直到本地文件的大小(loadedSize)大於等於要下載的文件(fileLength)大小時,退出該循環。

在不斷檢測的過程中,通過mHandler.sendMessage(mHandler.obtainMessage()); ,讓UI線程更新進度條。

下載線程,會不斷將服務器返回的數據流,寫到本地文件中,所以,本地文件的大小會不斷變化,直到,它的大小跟要下載的文件的大小相等時,就退出這個不斷檢測本地文件大小的線程。

其它沒有在上述代碼中表現出來的內容(在其它部分的代碼中):

1.在invokeFile( final BaseRequestLims request)方法中,開了一個如下的下載線程.該下載線程,會將服務器返回的文件流,寫到本地文件(localFile)中;然後,它還會發送一個標識為SAVE_DOWNLOAD廣播,包含的信息有要下載文件的文件大小fileLength。

//下載的子線程
   new Thread(){
    @Override
    public void run() {
     super.run();
     HttpHelper.invoke(request);
    }
   }.start();

上述代碼存在的問題:

1.上下文,使用的是某個Activity,如果發生系統調用了該Activity的onDestroy()時,下載線程還沒有完成,也就意味著,loadedSize的大小還是小於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();

下載線程:

new Thread(){
        @Override
        public void run() {
          super.run();
          HttpHelper.invoke(request);
        }
      }.start();

那麼,會出現什麼問題呢?

1).我可以確定的就是,mContext會出現洩漏。

2). DownLoadReceiver不能正常被取消注冊。

分析,待續。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved