Android中帶有進度條百分比顯示的可以從網絡下載文件的適配器
https://blog.csdn.net/SunBo_Java/article/details/8234092
該Demo拋棄了ListView控件的使用,是直接使用ViewGroup或其子類進行多個子控件封裝,從而達到修正多個附件同時下載時,列表中每個控件的顯示錯亂的問題(如有更好的方法,歡迎交流)。
該Demo采用單線程下載模式,因為項目的需求,所以一直沒改。大家可以直接將單線程改為多線程同步,因為該Demo中所用到的適配器就是根據多線程同步而設計的。
下麵我會給出整個Demo的完整範例,但沒有程序源碼,大家可以直接Copy,因為這是直接從我項目中的抽出來的,還請見諒!
好了,廢話不多說,開始:
1,先看看適配器的每個Item布局
- <RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
- xmlns:tools="https://schemas.android.com/tools"
- style="@style/width_fullscreen"
- android:padding="7dp"
- android:background="@drawable/list_selector_bg">
- <TextView
- android:id="@+id/AffixName"
- style="@style/width_fullscreen"
- android:textSize="17sp"
- android:textStyle="bold"
- android:maxLines="2"
- android:drawablePadding="3.4dp"
- android:layout_toLeftOf="@+id/AffixDownload" />
- <TextView
- android:id="@+id/AffixNotfoundFileErrormsg"
- style="@style/width_fullscreen"
- android:text="@string/download_notfoundfile_errormsg"
- android:textSize="12sp"
- android:textColor="@color/red"
- android:layout_marginTop="5dp"
- android:layout_marginLeft="20dp"
- android:layout_marginRight="25dp"
- android:drawableLeft="@drawable/message_status_fail"
- android:layout_below="@+id/AffixName"
- android:background="@drawable/popup"
- android:visibility="gone" />
- <Button
- android:id="@+id/AffixDownload"
- style="@style/width_height_free"
- android:text="@string/download"
- android:textColor="@color/DarkSlateGray"
- android:paddingLeft="10.5dp"
- android:paddingRight="10.5dp"
- android:drawableRight="@drawable/icon_download_ics"
- android:drawablePadding="3dp"
- android:layout_alignParentRight="true"
- android:layout_alignTop="@+id/AffixName"
- android:background="@drawable/button_call_bg" />
- <RelativeLayout
- android:id="@+id/AffixDownloadProgressPanel"
- style="@style/width_fullscreen"
- android:layout_below="@+id/AffixDownload"
- android:layout_marginTop="6.5dp"
- android:visibility="gone">
- <ProgressBar
- android:id="@+id/AffixDownloadProgressbar"
- style="?android:attr/progressBarStyleHorizontal"
- android:layout_width="match_parent"
- android:layout_height="13dp"
- android:progressDrawable="@drawable/progressbar_background" />
- <TextView
- android:id="@+id/AffixDownloadProgressValue"
- style="@style/width_height_free"
- android:textSize="11sp"
- android:textColor="@color/ghostwhite"
- android:layout_centerHorizontal="true" />
- </RelativeLayout>
- </RelativeLayout>
2,對應的適配器類:
- import java.io.File;
- import java.util.List;
- import android.content.Context;
- import android.content.SharedPreferences;
- import android.content.SharedPreferences.Editor;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.Message;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.view.ViewGroup;
- import android.widget.Button;
- import android.widget.ProgressBar;
- import android.widget.RelativeLayout;
- import android.widget.TextView;
- import com.hwttnet.oa.mobile.aas.R;
- import com.hwttnet.oa.mobile.app.App;
- import com.hwttnet.oa.mobile.app.App.Shared;
- import com.hwttnet.oa.mobile.listener.OnThreadListener;
- import com.hwttnet.oa.mobile.service.ThreadService;
- import com.hwttnet.oa.mobile.util.LocationDataProcess;
- import com.hwttnet.oa.mobile.util.ViewUtil;
- import com.hwttnet.other.model.AffixInfoBean;
- /**
- * 提供多附件下載時的列表適配器
- * <HR>
- * 作者:孫博
- * <P>
- * 時間:2012-11-26 下午4:08:33
- * <P>
- * 電子郵件:sunb@hwttnet.com
- * <P>
- * QQ:497733379
- * <P>
- * Gmail : sunbo.java@gmail.com
- */
- public class AffixDownloadAdapter implements OnClickListener, OnThreadListener
- {
- private final Context context;
- private final SharedPreferences affixShared;
- private final ThreadService threadService = new ThreadService();
- private final LocationDataProcess locationDateProcess;
- private final ViewUtil mViewUtil;
- public AffixDownloadAdapter(Context context)
- {
- this.context = context;
- affixShared = context.getSharedPreferences(Shared.DOWNLOADAFFIXINFO, Context.MODE_PRIVATE);
- threadService.setOnThreadListener(this);
- locationDateProcess = new LocationDataProcess(context);
- mViewUtil = new ViewUtil(context);
- }
- public void setupViews(ViewGroup mViewGroup, List<AffixInfoBean> affixs)
- {
- if(null == mViewGroup)
- return;
- if(mViewGroup.getChildCount() > 0)
- mViewGroup.removeAllViews();
- LayoutInflater layoutInflater = LayoutInflater.from(context);
- for(AffixInfoBean affix : affixs)
- {
- ViewHolder mViewHolder = new ViewHolder();
- mViewHolder.affix = affix;
- mViewHolder.isOpen = false;
- View convertView = layoutInflater.inflate(R.layout.affix_download_item, null);
- mViewHolder.mAffixName = (TextView) convertView.findViewById(R.id.AffixName);
- mViewHolder.mNotfoundFileErrormsg = (TextView) convertView.findViewById(R.id.AffixNotfoundFileErrormsg);
- mViewHolder.mButton = (Button) convertView.findViewById(R.id.AffixDownload);
- mViewHolder.mDownloadProgressPanel = (RelativeLayout) convertView.findViewById(R.id.AffixDownloadProgressPanel);
- mViewHolder.mProgressBar = (ProgressBar) convertView.findViewById(R.id.AffixDownloadProgressbar);
- mViewHolder.mDownloadProgressValue = (TextView) convertView.findViewById(R.id.AffixDownloadProgressValue);
- String identityName = affix.getAffixId() + affix.getAffixName();
- String key = identityName.substring(0, identityName.lastIndexOf("."));
- String affixAbspath = affixShared.getString(key, null);
- if(affixAbspath != null)
- {
- mViewHolder.mAffixName.setCompoundDrawablesWithIntrinsicBounds(R.drawable.result_ok, 0, 0, 0);
- mViewHolder.mButton.setText(R.string.open);
- mViewHolder.mButton.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.icon_open_file, 0);
- mViewHolder.isOpen = true;
- }
- mViewHolder.mAffixName.setText(affix.getAffixName());
- mViewHolder.mButton.setTag(mViewHolder);
- mViewHolder.mButton.setOnClickListener(this);
- mViewGroup.addView(convertView);
- }
- }
- @Override
- public void onClick(View v)
- {
- Object object = v.getTag();
- if(object instanceof ViewHolder)
- {
- ViewHolder mViewHolder = (ViewHolder) object;
- if(mViewHolder.isOpen)
- {
- AffixInfoBean affix = mViewHolder.affix;
- String key = affix.getAffixId() + affix.getAffixName();
- String affixAbspath = affixShared.getString(key.substring(0, key.lastIndexOf(".")), "");
- File file = new File(affixAbspath);
- if(!file.exists())
- {
- mViewHolder.mButton.setText(R.string.redownload);
- mViewHolder.mButton.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.icon_download_ics, 0);
- mViewHolder.mAffixName.setCompoundDrawablesWithIntrinsicBounds(R.drawable.attitude_falseinfo_icon, 0, 0, 0);
- mViewUtil.showAnimView(mViewHolder.mNotfoundFileErrormsg);
- mViewHolder.isOpen = false;
- } else
- switch(locationDateProcess.openFile(affixAbspath))
- {
- // 成功打開
- case 0:
- break;
- // 沒有找到被打開的文件
- case -1:
- break;
- // 沒有找到對應的查看編輯器
- case -2:
- App.makeText(context, R.string.find_no_editor);
- break;
- }
- } else
- if(!threadService.isAlive())
- {
- threadService.setTag(mViewHolder);
- threadService.start();
- } else
- App.makeText(context, R.string.please_wait);
- }
- }
- @Override
- public void onRun(Handler mHandler)
- {
- ViewHolder mViewHolder = (ViewHolder) threadService.getTag();
- String fileName = mViewHolder.affix.getAffixName();
- String downloadUrl = mViewHolder.affix.getDownloadUrl();
- locationDateProcess.download(mHandler, fileName, downloadUrl);
- }
- @Override
- public void onResult(Message msg)
- {
- ViewHolder mViewHolder = (ViewHolder) threadService.getTag();
- Bundle data = msg.getData();
- int filesize = data.getInt("FILE_SIZE");
- switch(msg.what)
- {
- // 下載成功
- case 0:
- mViewHolder.mProgressBar.setProgress(filesize);
- mViewHolder.mDownloadProgressValue.setText(R.string.download_ok);
- mViewHolder.mAffixName.setCompoundDrawablesWithIntrinsicBounds(R.drawable.result_ok, 0, 0, 0);
- mViewHolder.mButton.setText(R.string.open);
- mViewHolder.mButton.setEnabled(true);
- mViewHolder.mButton.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.icon_open_file, 0);
- mViewHolder.isOpen = true;
- String filePath = data.getString("FILE_CACHE_PATH");
- Editor editor = affixShared.edit();
- String key = mViewHolder.affix.getAffixId() + mViewHolder.affix.getAffixName();
- editor.putString(key.substring(0, key.lastIndexOf(".")), filePath);
- editor.commit();
- break;
- // 開始下載
- case 1:
- mViewUtil.hideAnimView(mViewHolder.mNotfoundFileErrormsg, false);
- mViewUtil.showAnimView(mViewHolder.mDownloadProgressPanel);
- mViewHolder.mAffixName.setCompoundDrawablesWithIntrinsicBounds(R.drawable.icon_download_manage_downloading, 0, 0, 0);
- mViewHolder.mProgressBar.setMax(filesize);
- mViewHolder.mDownloadProgressValue.setText(R.string.start_download);
- mViewHolder.mButton.setText(R.string.downloading);
- mViewHolder.mButton.setEnabled(false);
- break;
- // 正在下載
- case 2:
- int downProgress = data.getInt("DOWN_PROGRESS");
- int progress = (int) ((((float) downProgress) / ((float) filesize)) * 100);
- mViewHolder.mProgressBar.setProgress(downProgress);
- mViewHolder.mDownloadProgressValue.setText(progress + "%");
- break;
- // 下載失敗
- case -1:
- mViewHolder.mAffixName.setCompoundDrawablesWithIntrinsicBounds(R.drawable.icon_download_manage_fail, 0, 0, 0);
- mViewHolder.mDownloadProgressValue.setText(R.string.download_failed);
- mViewHolder.mButton.setText(R.string.retry);
- mViewHolder.mButton.setEnabled(true);
- mViewHolder.isOpen = false;
- break;
- // 文件已存在
- case -2:
- mViewUtil.hideAnimView(mViewHolder.mDownloadProgressPanel, false);
- mViewHolder.mAffixName.setCompoundDrawablesWithIntrinsicBounds(R.drawable.result_ok, 0, 0, 0);
- mViewHolder.mButton.setText(R.string.open);
- mViewHolder.mButton.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.icon_open_file, 0);
- mViewHolder.mButton.setEnabled(true);
- mViewHolder.isOpen = true;
- String haveFilePath = data.getString("FILE_CACHE_PATH");
- Editor haveEditor = affixShared.edit();
- String haveKey = mViewHolder.affix.getAffixId() + mViewHolder.affix.getAffixName();
- haveEditor.putString(haveKey.substring(0, haveKey.lastIndexOf(".")), haveFilePath);
- haveEditor.commit();
- App.makeText(context, R.string.file_already_exists);
- break;
- // 創建文件失敗
- case -3:
- mViewUtil.hideAnimView(mViewHolder.mDownloadProgressPanel, false);
- App.makeText(context, R.string.download_failed);
- break;
- }
- }
- private final class ViewHolder
- {
- private TextView mAffixName;
- private TextView mNotfoundFileErrormsg;
- private Button mButton;
- private RelativeLayout mDownloadProgressPanel;
- private ProgressBar mProgressBar;
- private TextView mDownloadProgressValue;
- private boolean isOpen;
- private AffixInfoBean affix;
- }
- }
類中所用到的其他相關類和方法:
1,ThreadService.java
- import android.os.Handler;
- import android.os.Message;
- import com.hwttnet.oa.mobile.listener.OnThreadListener;
- /**
- * 服務於整個程序中所有耗時的操作,調用{@link #start()}方法即可將耗時的程序轉入新線程中執行
- * <P>
- * <I>線程執行方法不保證線程安全和數據傳輸絕對正常</I>
- * <P>
- * 該類不可被繼承
- * <HR>
- * 作者:孫博
- * <P>
- * 時間:2012-10-18 下午3:42:55
- * <P>
- * 電子郵件:sunb@hwttnet.com
- * <P>
- * QQ:497733379
- * <P>
- * Gmail : sunbo.java@gmail.com
- */
- public final class ThreadService
- {
- private Thread thread;
- private Object tag;
- private OnThreadListener onThreadListener;
- private final Handler mHandler = new Handler()
- {
- @Override
- public void handleMessage(Message msg)
- {
- if (onThreadListener != null)
- onThreadListener.onResult(msg);
- }
- };
- /**
- * 開啟一個新的線程來執行一些耗時的操作
- * <P>
- * 注意:<I>在調用該方法之前應該先為其設置線程運行監聽器:
- * <P>
- * {@link #setOnThreadListener(OnThreadListener)} </I>
- */
- public void start()
- {
- thread = new Thread()
- {
- @Override
- public void run()
- {
- if (onThreadListener != null)
- onThreadListener.onRun(mHandler);
- }
- };
- thread.start();
- }
- /**
- * 檢測線程是否處於活動狀態
- *
- * @return 如果是活動狀態,返回{@code true},否則返回{@code false}
- */
- public boolean isAlive()
- {
- if (thread != null)
- return thread.isAlive();
- return false;
- }
- /**
- * 為當前執行的線程設置運行時監聽器以實時捕捉線程運行時到運行結束的過程
- *
- * @param onThreadListener
- * 定義了線程運行時到運行結束的過程的監聽器對象
- */
- public void setOnThreadListener(OnThreadListener onThreadListener)
- {
- this.onThreadListener = onThreadListener;
- }
- public Object getTag()
- {
- return tag;
- }
- public void setTag(Object tag)
- {
- this.tag = tag;
- }
- }
2,OnThreadListener.java
- import android.os.Handler;
- import android.os.Message;
- /**
- * 線程調用時的回調接口,該接口中定義了線程運行時和結束後的回調方法
- * <HR>
- * 作者:孫博
- * <P>
- * 時間:2012-10-18 下午2:48:11
- * <P>
- * 電子郵件:sunb@hwttnet.com
- * <P>
- * QQ:497733379
- * <P>
- * Gmail : sunbo.java@gmail.com
- */
- public interface OnThreadListener
- {
- /**
- * 監聽線程開始後的運行時狀態,可在該方法中執行需要線程來操作的程序
- *
- * @param mHandler
- * 已實例化且做好在線程中發送消息的對象
- */
- public void onRun(Handler mHandler);
- /**
- * 監聽線程在結束後的狀態,可在該方法中執行線程結束後需要操作的程序
- *
- * @param msg
- * 在線程運行時得到的一個裝載著消息內容的消息對象
- */
- public void onResult(Message msg);
- }
3,LocationDataProcess.java
- import java.io.BufferedOutputStream;
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.net.URL;
- import java.net.URLConnection;
- import java.text.SimpleDateFormat;
- import java.util.Date;
- import java.util.LinkedHashMap;
- import android.content.ActivityNotFoundException;
- import android.content.Context;
- import android.content.Intent;
- import android.content.SharedPreferences;
- import android.content.SharedPreferences.Editor;
- import android.content.res.Resources;
- import android.net.Uri;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.Message;
- import com.hwttnet.oa.mobile.aas.R;
- import com.hwttnet.oa.mobile.app.App;
- /**
- * 本類包含了用於處理本地數據的基本方法:
- * <UL>
- * <LI>記錄並獲取程序中每個列表刷新的時間</LI>
- * </UL>
- * <HR>
- * 作者:孫博
- * <P>
- * 時間:2012-10-18 上午11:29:49
- * <P>
- * 電子郵件:sunb@hwttnet.com
- * <P>
- * QQ:497733379
- * <P>
- * Gmail : sunbo.java@gmail.com
- *
- */
- public class LocationDataProcess
- {
- private final Context context;
- /**
- * @param context
- * 正在運行時的程序上下文對象
- */
- public LocationDataProcess(Context context)
- {
- this.context = context;
- }
- /**
- * 從網絡中下載文件
- *
- * <PRE>
- * Message msg = mHandler.obtainMessage();
- * msg.what = msgWhat; // -1:失敗;-2:文件已存在;-3:新文件創建失敗;0:成功;1:開始下載;2:下載過程中
- * Bundle data = msg.getData();
- * data.putInt("<B>FILE_SIZE</B>", fileSize);
- * data.putInt("<B>DOWN_PROGRESS</B>", downProgress);
- * data.putString("<B>FILE_CACHE_PATH</B>", imageFilePath);
- * mHandler.sendMessage(msg);
- * </PRE>
- *
- * @param mHandler
- * 處理實時跟蹤下載中向主線程發送的消息隊列,一個已經被實例化的消息處理對象
- * @param fileName
- * 要下載的文件標準名稱,含後綴
- * @param downloadUrl
- * 一個標準的網絡文件{@code HTTP}地址
- * @throws IOException
- * 如果網絡異常或讀取圖片流出現問題,則拋出該異常
- */
- public void download(Handler mHandler, String fileName, String downloadUrl)
- {
- if (null == mHandler || null == downloadUrl)
- {
- this.sendMessage(mHandler, -1, 0, 0, null);
- return;
- }
- try
- {
- int downProgress = 0;
- URL url = new URL(downloadUrl);
- URLConnection connection = url.openConnection();
- connection.setConnectTimeout(1000 * 30);
- connection.connect();
- InputStream inputStream = connection.getInputStream();
- int fileSize = connection.getContentLength();
- if (fileSize < 1 || null == inputStream)
- this.sendMessage(mHandler, -1, fileSize, downProgress, null);
- else
- {
- this.sendMessage(mHandler, 1, fileSize, downProgress, null);
- File downloadFolder = new File(App.AFFIXSTORAGEPATH);
- if (!downloadFolder.exists())
- downloadFolder.mkdirs();
- File downloadFile = new File(downloadFolder.getAbsolutePath() + "/" + fileName);
- if (downloadFile.exists())
- this.sendMessage(mHandler, -2, fileSize, downProgress, downloadFile.getAbsolutePath());
- else if (downloadFile.createNewFile())
- {
- byte[] buffer = new byte[1024 * 8];
- int length = -1;
- BufferedOutputStream bufferOutStream = new BufferedOutputStream(new FileOutputStream(downloadFile));
- while ((length = inputStream.read(buffer)) != -1)
- {
- bufferOutStream.write(buffer, 0, length);
- downProgress += length;
- this.sendMessage(mHandler, 2, fileSize, downProgress, downloadFile.getAbsolutePath());
- }
- bufferOutStream.flush();
- bufferOutStream.close();
- inputStream.close();
- this.sendMessage(mHandler, 0, fileSize, downProgress, downloadFile.getAbsolutePath());
- } else
- this.sendMessage(mHandler, -3, fileSize, downProgress, null);
- }
- // 異常捕捉應該更詳細
- } catch (IOException e)
- {
- e.printStackTrace();
- this.sendMessage(mHandler, -1, 0, 0, null);
- }
- }
- private void sendMessage(Handler mHandler, int msgWhat, int fileSize,
- int downProgress, String imageFilePath)
- {
- Message msg = mHandler.obtainMessage();
- msg.what = msgWhat;
- Bundle data = msg.getData();
- data.putInt("FILE_SIZE", fileSize);
- data.putInt("DOWN_PROGRESS", downProgress);
- data.putString("FILE_CACHE_PATH", imageFilePath);
- mHandler.sendMessage(msg);
- }
- /**
- * 根據指定的文件路徑自動在係統中尋找與之對應的編輯器並打開該文件
- * <P>
- * 支持共計38種不同後綴的文件,主要可被分類為:
- *
- * @param filePath
- * 一個有效的文件絕對路徑
- * @return 返回一個打開時的狀態,具體如下:
- * <UL>
- * <LI>0:表示成功打開</LI>
- * <LI>-1:表示無法找到被打開的文件</LI>
- * <LI>-2:表示無法找到打開該文件的相關編輯器</LI>
- * </UL>
- */
- public int openFile(String filePath)
- {
- File openFile = new File(filePath);
- if (!openFile.exists())
- return -1;
- int openStauts = 0;
- String filename = openFile.getName();
- String suffixName = filename.substring(filename.lastIndexOf("."), filename.length());
- try
- {
- Resources r = context.getResources();
- String[] officEndingNames = r.getStringArray(R.array.FILEENDINGOFFIC);
- for(String endingName : officEndingNames)
- if(suffixName.equals(endingName))
- context.startActivity(this.getDefaultFileIntent(openFile));
- String[] mediaEndingNames = r.getStringArray(R.array.FILENDINGMEDIA);
- for(String endingName : mediaEndingNames)
- if(suffixName.equals(endingName))
- context.startActivity(this.getMediaFileIntent(openFile));
- String[] htmlEndingNames = r.getStringArray(R.array.FILEENDINGHTML);
- for(String endingName : htmlEndingNames)
- if(suffixName.equals(endingName))
- context.startActivity(this.getHtmlFileIntent(openFile));
- String[] packEndingNames = r.getStringArray(R.array.FILEENDINGPACK);
- for(String endingName : packEndingNames)
- if(suffixName.equals(endingName))
- context.startActivity(this.getPackFileIntent(openFile));
- } catch (ActivityNotFoundException e)
-
最後更新:2017-04-04 07:03:56
上一篇:
電子產品,讓人類無溝通能力?
下一篇:
Win 8 VS OS X Mountain Lion,誰是王者?