Android有用的任務管理器—tractor
在平時的android開發工作中,我們常常須要運行耗時操作,有時為了用戶體驗還須要顯示個等待框,我之前的做法都是開一個線程,然後用handler發消息進行顯示和關閉等待框以及相關的ui操作。假設任務比較多的話,頻繁的new Thread會讓代碼看上去比較混亂,並且還不好管理,針對這樣的情況我寫了tractor。
tractor基本的作用有:
1. 代碼變得整潔。不用在到處new Thread和new Handler。
2. 能夠監控任務的運行情況,能夠隨時取消一個或多個任務;
3. 封裝了okhttp。支持大文件上傳,多線程斷點下載。get,post以及其它的網絡請求
效果圖
使用說明
類圖
結構事實上非常easy。沒有多少東西。
普通任務
//當LoadListenerImpl構造函數傳入context,則顯示progressdialog
doNormalTask(new LoadListenerImpl(this) {
@Override
public void onStart(Object result) {
super.onStart(result);
setMessage("任務開始運行");
}
@Override
public void onSuccess(Object result) {
super.onSuccess(result);
String response = (String) result;
setMessage("任務結束");
}
@Override
public void onFail(Object result) {
super.onFail(result);
String response = (String) result;
setMessage(response);
}
@Override
public void onLoading(Object result) {
super.onLoading(result);
//以後不用寫handler了,這樣就能夠處理了
int response = (int) result;
switch (response) {
case 1:
setMessage("正在運行 response=" + response);
break;
case 2:
setMessage("正在運行 response=" + response);
break;
case 3:
setMessage("正在運行 response=" + response);
break;
default:
break;
}
}
@Override
public void onCancel(Object result) {
super.onCancel(result);
setMessage("任務被取消了");
}
@Override
public void onCancelClick() {
super.onCancelClick();
TaskPool.getInstance().cancelTask(MainActivity.this);
}
}, this);
在上面的代碼塊中,LoadListenerImpl是LoadListener的實現類,用於監聽任務載入的整個過程,使用LoadListenerImpl而不是LoadListener的優點有兩點:
1.能夠不實現全部的方法,僅僅要依據自己的須要來實現對應的方法即可了;‘
2.LoadListenerImpl中能夠管理ProgressDialog。ProgressDialog能夠用tractor中自帶的,也能夠自定義。
LoadListenerImpl 部分源代碼:
public class LoadListenerImpl implements LoadListener {
private WeakReference<Context> context;
private ProgressDialog mProgressDialog;
private String mMessage = "載入中...";
private long mDismissTime = 500;
/**
* 不顯示progressdialog
*/
public LoadListenerImpl() {
}
/**
* 顯示progressdialog。其上顯示的文字是默認的
* @param context
*/
public LoadListenerImpl(Context context) {
init(context, null);
}
/**
* 顯示progressdialog,其上顯示的文字是message
* @param context
* @param message
*/
public LoadListenerImpl(Context context, String message) {
init(context, message);
}
/**
* 設置自定義的progressdialog,假設不設置則使用tractor自帶的
* @param progressDialog
*/
public void setProgressDialog(ProgressDialog progressDialog) {
mProgressDialog = progressDialog;
}
......
}
當然了,你也能夠自己實現LoadListener。畢竟是面向接口編程。
doNarmalTask方法的詳細實現
/**
* 發起個普通的任務
*
* @param listener
* @param tag
*/
public void doNormalTask(LoadListener listener, Object tag) {
TaskPool.getInstance().execute(new Task(tag, listener) {
@Override
public void onRun() {
SystemClock.sleep(500);
notifyLoading(1);
SystemClock.sleep(500);
notifyLoading(2);
SystemClock.sleep(500);
notifyLoading(3);
SystemClock.sleep(500);
Random random = new Random();
//任務是模擬的,所以隨機下
if (random.nextBoolean()) {
//notifySuccess(null);
} else {
notifyFail("糟糕,任務失敗了");
}
}
@Override
public void cancelTask() {
}
});
}
TaskPool.getInstance().execute()方法終於是把task交由線程池來運行。TaskPool僅僅負責加入和取消任務。接下來說Task,在上面的類圖中有說明,Task是實現了Runnable接口,並重寫run(),所以線程池能夠運行Task,我們看下run()方法是怎麽實現的:
public abstract class Task implements Runnable {
......
@Override
public final void run() {
start();
onRun();
finish();
}
......
private void start() {
notifyStart(null);
......
}
/**
* 實現這種方法來運行詳細的任務
*/
public abstract void onRun();
private void finish() {
if (isRunning()) {
// 默認載入成功
mStatus = Status.SUCCESS;
notifySuccess(null);
}
clear();
}
run()中分別運行了start(),onRun()和finish(),start()方法中調用了notifyStart(null),finish()中調用了notifySuccess(null),也就是說在開始的時候會通知ui線程任務開始,結束的時候默認通知ui線程任務結束。
onRun()是抽象方法,是給任務調用者來實現運行詳細的任務的。在運行的過程中能夠通過notifyLoading(result)來通知ui任務的進度。notifySuccess(result)和notifyFail(result)通知ui任務成功和失敗,並把須要的數據result作為參數傳給ui線程。
至於Task中的cancelTask()放到後面取消任務的時候再說。
超時任務
doTimeoutTask(500, new LoadListenerImpl() {
@Override
public void onStart(Object result) {
super.onStart(result);
toast("超時任務開始運行");
}
@Override
public void onSuccess(Object result) {
super.onSuccess(result);
toast("超時任務運行成功");
}
@Override
public void onTimeout(Object result) {
super.onTimeout(result);
toast("任務超時");
}
}, this);
.......
public void doTimeoutTask(long timeout, LoadListener listener, Object tag) {
TaskPool.getInstance().execute(new Task(timeout, tag, listener) {
@Override
public void onRun() {
SystemClock.sleep(1000);
}
@Override
public void cancelTask() {
}
});
}
能夠看到。超時任務相較於普通任務來說僅僅是Task構造函數多了個timeout參數。這個timeout參數的含義就是任務運行的時間限制。假設超過這個限制就回調onTimeout()方法。
取消任務
在平時的開發過程中,有時開了一個超耗時的操作,在耗時操作未返回的時候頁面就被關閉了。當頁面關閉以後耗時操作才有了返回,這時候須要操作控件的話就有可能會報null或者其它的一些異常,為了避免異常,我們通常須要進行一些頁面是否處於激活狀態的推斷,但是這樣總是非常麻煩的。tractor攻克了這個問題,能夠調用取消任務的方法,就像這樣:
//取消任務的方法,參數能夠是任務的tag,也能夠是task。假設是tag,則取消tag相關的全部任務。是task則取消指定的task。
//能夠在onDestroy()中調用
TaskPool.getInstance().cancelTask(tag|task);
這樣調用以後會調用notifyCancel(null),在ui上顯示給用戶任務已取消的效果,tractor有個特性:當任務有結果時(已經取消,超時,成功和失敗),興許的notifyXXX()就都不會通知到ui線程了,所以假設任務在運行取消任務代碼以後,當任務有結果返回的時候。ui回調也不會被運行。那麽上面說的那個問題也就不存在了,就省的自己去加推斷了。
前面也有提到,取消任務的代碼僅僅能在保證ui上有取消的效果,但是任務實際上還是在運行的。盡管用戶看不到但是資源還是在損耗,所以還不行。
從類圖中能看到Task有onRun()和cancelTask()兩個抽象方法,onRun()是運行詳細任務的,cancelTask()則是運行詳細的取消任務的操作。他是在非ui線程中運行的。詳細怎麽停止任務是由你來決定的。
網絡請求部分
為了讓任務管理器看起來更實用些。我封裝了網絡框架,實現是okhttp,能夠支持head,get,post,多線程下載,大文件上傳以及其它一些http請求。因為是面向接口編程,所以假設以後有更合適的庫,能夠非常方便的就換掉okhttp。這部分的樣例我就不貼出來了,感興趣能夠自己看代碼,非常easy,代碼全在demo module的MainActivity裏。
下載:
上傳打文件:
最後
假設你有什麽問題和建議能夠留言或者給我發郵件。tractor是托管在github上,點擊此處獲取源代碼。歡迎star or follow!
Android有用的任務管理器—tractor