使用Thread打造上傳下載器

鋸齒流沙發表於2018-01-09

專案中常常需要上傳圖片、帖子或者使用者下載apk更新應用等等,因為上傳過程中需要儲存一些狀態,比如進度條、傳送狀態(成功、失敗、重發、停止)等狀態,所以需要打造一個上傳下載器。剛剛開始的時候的想法是重寫thread,在裡面儲存這些狀態,後來考慮到使用者需要頻繁的發帖和上傳圖片等等而且考慮到使用者可以併發做這些任務,所以就改用執行緒池來實現上傳下載器。廢話不多說,馬上帶你打造上傳下載器。

新建一個上傳下載管理器ThreadManager

private int total=100;//進度條更新總進度

private Handler mHandler;//執行緒間通訊的handler機制

private ArrayList<Info> mInfos;;//資訊儲存佇列

private ThreadManagerListener mListener;//進度回撥

private static ThreadManager mThreadManager;//上傳下載器的例項

private ExecutorService mExecutorService;//執行緒池

上傳下載器需要使用單例模式,不需要頻繁建立這個例項來消耗記憶體

private ThreadManager(){

if(mHandler==null){

mHandler=newHandler();

}

if(mExecutorService==null){

mExecutorService= Executors.newFixedThreadPool(3);

}}

public static ThreadManager getInstance(){

if(mThreadManager==null){

synchronized(ThreadManager.class){

if(mThreadManager==null){

mThreadManager=newSpeakThreadManager();

}}}

mThreadManager;

}

狀態資訊類,可以放到管理器中作為內部類也可以作為外部類,使用者需要什麼狀態的資訊就儲存在這裡就行了,主要看你需要什麼資訊

public static class Info{

private int id;

public String content;

public int code=0;//狀態返回碼

public String message="正在傳送";//提示資訊

public UploadManager.MultiUploadDataimgData;//圖片資訊

public boolean istop=false;

public boolean isprogress=false;

public boolean updateSpeakImage=false;

public boolean isReSpeakThread=false;

public int progressSize=5;//傳送進度

public int uploadSize=0;//更新進度

public boolean isFail=false;

public int len=0;//圖片大小

public int size=0;//已經傳送的進度

}

管理器中資訊儲存佇列,主要的作用是確保每個執行緒中對應一個info狀態儲存資訊

傳送資料加入到佇列中

public void addInfo(Info info){

if(mInfos==null){

mInfos=newArrayList<Info>();

}

mInfos.add(info);

}

根據id獲取你需要的傳送資料

public ArrayList<Info> getReleaseThreadInfo(int mId){

Info releInfo = null;

if(mInfos!=null&&mInfos.size() >0){

for(Info mInfo :mInfos)

{

if(mInfo.id== mId){

releInfo = mInfo;

}}}

return releInfo;

}  

//傳送成功或者取消傳送之後呼叫,移除已經存在的info

public boolean removeArrayInfo(Info info){

boolean flag =false;

if(mInfos!=null&&mInfos.size() >0){

if(mInfos.contains(info)){

mInfos.remove(info);

flag =true;

}}

if(mInfos!=null&&mInfos.size() <=0){

mInfos.clear();

}

return flag;

}

監控狀態回撥

public interface ThreadManagerListener{

public void onprogress(int total, int progressSize,Info info);

public void finish(ResultMessage info,Info info);

}

public void setThreadManagerListener(Info info,ThreadManagerListener l){

this.mListener= l;

startThreak(info);//開啟耗時任務操作

}

//更新進度

private void updateProgress(final intuploadSize, final Info info){

if(mListener!=null){

mHandler.post(newRunnable(){

@Override

public voidrun(){

mListener.onprogress(total,uploadSize,info);//更新進度

}

});

//上傳最終狀態

private void uploadFinish(final ResultMessage result, final Info info){

if(mListener!=null){

mHandler.post(newRunnable(){

public voidrun(){

if(result!=null){

mListener.finish(result,info);

}else{

ResultMessage post =newResultMessage();

post.code= -1;

post.msg="釋出失敗";

mListener.finish(post,info);

}}});

}}

下面看startSpeakThreak方法,主要是線上程池中做上傳下載的耗時任務,如果需要更新進度條的話直接呼叫updateProgress方法,上傳下載任務完成需要呼叫uploadFinish方法,把需要實現的邏輯放到裡面執行就可以了,由於這個方法是開啟子執行緒的,所以需要更新ui的操作需要呼叫handler來更新。

private void startSpeakThreak(final Info info){

mExecutorService.submit(newRunnable(){

@Override

public void run(){

//這裡實現耗時任務的邏輯

try{

}catch(Exception e){

e.printStackTrace();

}}});

}

使用的話只需要將傳送的資訊首先加入到傳送佇列releaseThread,然後再呼叫setThreadManagerListener方法設定回撥就可以了。

這裡主要是考慮到併發的情況,使用了執行緒池來實現,當然如果你不需要執行緒池也可以使用重寫thread類,將儲存資訊放在管理類就可以了,邏輯一樣的,看各自的業務需要。


相關文章