編輯:關於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不能正常被取消注冊。
分析,待續。
關於Android View 事件分發過程的文章網絡上可以搜到一把大,這裡貼一篇代碼性的文章,作者也是個牛人:Android事件分發機制完全解析,帶你從源碼的角度徹底理解
酷狗音樂最新版有ktv模式啦,大家想k歌的話不用去ktv也可以自已在家k歌,愛唱歌的朋友一起來學習下酷狗音樂怎麼k歌吧! 1.首先,打開酷狗這個軟件,建議
Android提供了 VideoView組件,它的作用與ImageView類似,只是ImageView用於顯示圖片,而VideoView用於播放視頻。 使用
在開發中,有時需要使用db文件數據庫,所以就需要將其導入項目,再將其使用程序寫入到應用的db文件下使用。 代碼很簡單,可以拿來直接使用。 要使用需要兩個步驟: 1.創建r