學以緻用--鍊式結構處理android耗時請求
1:背景
今天遇到了一個情況(首先需要去http請求擷取伺服器資料,然後将資料存庫,其次再将資料的一部分放入share檔案,最後更新記憶體資料.....) 哎,最後一步更新記憶體還行,非常速度的,前面散步基本是基本包括了android中耗時操作的三個大類吧,哎---是在不想一步一步整
2:知識前提
大概了解程式的設計模式(本文采用責任鍊模式),有一點點開發經驗就ok了哈
3:程式基本模型
一個請求類 Responser, 一個請求執行類ResponserChain,一個 HttpUtils工具類,一個資料庫工具類databaseutils,一個share檔案工具類shareutils
Responser代碼如下:
public abstract class Responser<T> {
public final int CONS_TIME_OUT_ONE_SECOND = 1000;
private final int CONS_TIME_OUT_SIXTEEN_SECOND = 60 * CONS_TIME_OUT_ONE_SECOND; // 10秒
public Responser(int weight) {
this.thisWeight = weight;
this.ResponserKey = String.valueOf(hashCode());
}
public String ResponserKey;<span style="white-space:pre"> </span>//唯一辨別一個任務
public int thisWeight = Integer.MAX_VALUE; //該請求的權重
protected T t;
public int timeOut() {
return CONS_TIME_OUT_SIXTEEN_SECOND;
}
/**
* 依次執行任務的時候,如果下一個任務需要上一次執行的傳回結果,在這裡設定
*
* @param ob
*/
public void doNext(JSONObject ob) {
}
/**
* 依次執行任務的時候,如果下一個任務需要上一次執行的傳回結果,在這裡擷取
*
* @param ob
*/
public T onNext() {
return t;
}
/**
* 執行任務
*
* @return
*/
public abstract String excute();
/**
* 任務類型
*
* @return
*/
public abstract EResponseType resType();
public enum EResponseType {
DATABASE, HTTP, SHARE
}
}
注意以上的一個excute的方法,每個請求類均有該方法執行
下面舉例說明以上遇到的情況,先http請求,再入庫,然後再share檔案,然後記憶體
<pre name="code" class="java">final Responser<String> http= new Responser<String>(0) {
@Override
public String excute() {
return HttpUtils.get(......);//省略号是請求位址
}
};
<pre name="code" class="java">final Responser<String> db= new Responser<String>(1) {
@Override
public String excute() {
return databaseutils.insert(......);//省略号是插入資料庫代碼
}
};
<pre name="code" class="java">final Responser<String> unbind = new <span style="font-family: Arial, Helvetica, sans-serif;">Responser</span><span style="font-family: Arial, Helvetica, sans-serif;"><String>(2) {</span>
@Override
public String excute() {
return shareutils.commit(......);//省略号是送出share檔案
}
};
然後是執行請求的類ResponserChain:
代碼如下
public class ResponserChain {
private Vector<Responser<?>> allResponse = new Vector<Responser<?>>();
private boolean currentChainIsAlive = false;
private responserChainListener _ResChainListener;
private Responser<?> _Responser;
/**
* Constructor one responseChain
*/
public ResponserChain(responserChainListener excuteListener, Responser<?>... responsers) {
if (responsers.length <= 0) {
return;
}
for (Responser<?> responser : responsers) {
allResponse.add(responser);
}
currentChainIsAlive = true;
_ResChainListener = excuteListener;
}
/**
* ready
*/
public boolean ready() {
synchronized (allResponse) {
if (allResponse.isEmpty()) {
return false;
}
for (Responser<?> responser : allResponse) {
if (_Responser == null || responser.thisWeight < _Responser.thisWeight) {
_Responser = responser;
}
}
if (_Responser == null) {
return false;
}
for (Responser<?> responser : allResponse) {
if (responser.ResponserKey.equals(_Responser.ResponserKey)) {
allResponse.remove(responser);
break;
}
}
return _Responser.thisWeight != Integer.MAX_VALUE;
}
}
/**
* go,
*/
public void go() {
HTTPThreadPool.getInstance().submit(new Runnable() {
@Override
public void run() {
/**
* 必須保證以下代碼執行的每一句的順序
*/
final String _task = _Responser.ResponserKey;
final int _timeout = _Responser.timeOut();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = _timeout; i > 0; i -= _Responser.CONS_TIME_OUT_ONE_SECOND) {
// 如果在計算逾時的時候,改任務已經執行結束,則結束超時
if (!currentChainIsAlive || !_Responser.ResponserKey.equals(_task)) {
return;
}
try {
Thread.sleep(1050); // 為什麼是1050呢--猜
}
catch (Exception e) {
}
}
if (currentChainIsAlive && _Responser.ResponserKey.equals(_task)) {
if (_ResChainListener != null) {
_ResChainListener.onExcuteChainCallBack(HttpConstans.HTTP_TIMEOUT, _Responser, null);
}
release();
}
}
}).start();
String result = _Responser.excute();
// 執行完成,但是職責鍊已經不存在
if (!currentChainIsAlive) {
return;
}
JSONObject json = null;
try {
if (!TextUtils.isEmpty(result)) {
json = new JSONObject(result);
}
}
catch (JSONException e) {
json = null;
}
if (json == null) {
if (_ResChainListener != null) {
_ResChainListener.onExcuteChainCallBack(HttpConstans.HTTP_FAILED, _Responser, null);
}
release();
return;
}
final int code = json.optInt("code");
if (_ResChainListener != null) {
_ResChainListener.onExcuteChainCallBack(code, _Responser, json);
}
_Responser.thisWeight = Integer.MAX_VALUE;
boolean hasNext = ready();
if (hasNext) {
_Responser.doNext(json);
}
if (code == 0 && hasNext) {
go();
return;
}
release();
}
});
}
/**
* cut current chain
*/
public void cut() {
release();
}
/**
* current chain is alive
*/
public boolean isAlive() {
return currentChainIsAlive;
}
/**
* dynamic add one response, but this response is excute lase
*/
public boolean addResponseToLase(Responser<?>... responsers) {
/** current chain is over, may be this object is destory */
if (!currentChainIsAlive) {
return false;
}
synchronized (allResponse) {
for (Responser<?> responser : responsers) {
allResponse.add(responser);
}
}
return true;
}
/**
* release
*/
public void release() {
currentChainIsAlive = false;
_ResChainListener = null;
allResponse.clear();
}
/**
* one chain excute result
*/
public interface responserChainListener {
public void onExcuteChainCallBack(int result, Responser<?> responser, JSONObject json);
}
}
最後執行你隻需要這樣.....
ResponserChain c = new ResponserChain(new responserChainListener() {
<span style="white-space:pre"> </span>@Override
<span style="white-space:pre"> </span>public void onExcuteChainCallBack(final int result, final Responser<?> responser, final JSONObject json) {
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>postUI(new Runnable() {
<span style="white-space:pre"> </span>@Override
<span style="white-space:pre"> </span>public void run() {
<span style="white-space:pre"> </span>//根據傳回的請求的類型,各種結果就出來了,而且是你制定的順序 http第一執行,db第二執行,share第三執行,
<span style="white-space:pre"> </span>}, http,db,share);
if (c.ready()) {
<span style="white-space:pre"> </span>c.go();
<span style="white-space:pre"> </span>return;
}
好了,這是為了處理開發中遇到的問題,代碼不是很高尚,品質也不是很好,隻是給各位初學android的碼友一種解決問題的方式,寫得不好,各位見諒了......