天天看點

學以緻用--鍊式結構處理android耗時請求學以緻用--鍊式結構處理android耗時請求

學以緻用--鍊式結構處理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的碼友一種解決問題的方式,寫得不好,各位見諒了......