android異步處理Handler+Thread使用進階(二)

在上篇文章《android異步處理Handler+Thread使用進階》中提到的問題做相應的方案,很多地方已經優化,這次的結構更加合理。

文章涉及的幾個知識點又必須要了解,如泛型,繼承,抽象方法,單例等。

設計思想和上次一樣,不同的是這次每一個線程對應一個Handler,handler和線程服務都不再使用static。基類設置抽象方法,即回調方法。同時設置泛型,來確定回調方法的返回值。

同時支持Fragment。

 

先看個登錄的例子:

MainActivity:

package com.sc.htdemo;

import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends BaseActivity<String> {

	private TextView tv;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		tv = (TextView) findViewById(R.id.tv);
		
		getRest().login(this, "zhangsan", "123");//這裏執行登錄
	}

	//回調方法。登錄完後執行,更新UI。
	@Override
	public void call(String result) {
		tv.setText(result);
	}

}

一句話執行登錄操作,一句話更新UI!

 

BaseActivity:

package com.sc.htdemo;

import android.app.Activity;

import com.sc.htdemo.app.Rest;

/**
 * @author SunnyCoffee
 * @Date 2013-7-18
 * @version 1.0
 * @Desc Activity的基類,泛型表示回調方法返回的數據類型
 */

// 使用泛型,這樣返回類型更精確
public abstract class BaseActivity<T> extends Activity {

	/**
	 * 獲取服務對象
	 * 
	 * @return
	 */
	public Rest<T> getRest() {
		return new Rest<T>();
	}

	/**
	 * 這是個回調方法,線程的內容執行完後進行回調。
	 * 
	 * @param result
	 */
	public abstract void call(T result);
}

Rest:

package com.sc.htdemo.app;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import android.os.Handler;
import android.os.Message;

import com.google.gson.Gson;
import com.sc.htdemo.BaseActivity;

/**
 * @Author SunnyCoffee
 * @Date 2013-7-29
 * @version 1.0
 * @Desc 獲取數據的接口類
 */

public class Rest<T> {

	private Gson gson = RestHelper.getGson();
	private ExecutorService service = RestHelper.getThreadPool();

	/**
	 * 用戶登錄
	 * 
	 * @param context
	 * @param acount
	 * @param pwd
	 */
	public void login(final BaseActivity<T> context, final String acount,
			final String pwd) {
		//創建一個handler和一個Thread
		final AppHandler<T> handler = new AppHandler<T>(context);
		Runnable thread = new Runnable() {
			@Override
			public void run() {
				// 這裏進行聯網解析操作
				// String json = HttpConn.get(context, acount);
				// Test test = gson.fromJson(json, Test.class);
				sendData(handler, "result");
			}
		};
		service.execute(thread);
	}

	private void sendData(Handler handler, Object obj) {
		Message msg = handler.obtainMessage();
		msg.obj = obj;
		handler.sendMessage(msg);
	}

}
//這裏使用單例。提供一個線程池和一個gson對象
final class RestHelper {
	private static final int THREAD_POOL_SIZE = 5;
	private static ExecutorService service = null;
	private static Gson gson = null;

	private RestHelper() {
	}

	public static ExecutorService getThreadPool() {
		if (service == null)
			service = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
		return service;
	}

	public static Gson getGson() {
		if (gson == null)
			gson = new Gson();
		return gson;
	}
}

Rest裏提供各種接口,如login(),regist(),getGoodList()等等。每個接口方法裏都創建一個Handler和一個Runnable。Handler用來接收服務器返回值,調用回調方法;Runable丟進線程池執行聯網、解析等耗時操作。

 

AppHandler:

package com.sc.htdemo.app;

import android.os.Handler;
import android.os.Message;

import com.sc.htdemo.BaseActivity;
import com.sc.htdemo.BaseFmt;


/**
 * @Author SunnyCoffee
 * @Date 2013-7-29
 * @version 1.0
 * @Desc Handler。獲得返回值,通過執行回調方法更新UI
 */
public class AppHandler<T> extends Handler {

	private BaseActivity<T> act;
	private BaseFmt<T> fmt;

	public AppHandler(BaseActivity<T> act) {
		this.act = act;
	}

	public AppHandler(BaseFmt<T> fmt) {
		this.fmt = fmt;
	}

	@Override
	public void handleMessage(Message msg) {
		if (msg.obj == null)
			return;
		
		@SuppressWarnings("unchecked")
		T result = (T) msg.obj;
		
		//這裏判斷一下Activity是否已經destroy
		if (act != null && !act.isFinishing())
			act.call(result);// 執行回調方法
		else if (fmt != null && fmt.isVisible())
			fmt.call(result);
	}
}

這裏增加了對Fragment的支持。對應的Fragment的基類:

BaseFmt,同activity的基類一樣:

package com.sc.htdemo;

import android.support.v4.app.Fragment;

import com.sc.htdemo.app.Rest;

/**
 * @author SunnyCoffee
 * @create 2013-8-6
 * @version 1.0
 * @desc Fragment的基類
 */

public abstract class BaseFmt<T> extends Fragment {

	/**
	 * 獲取服務對象
	 * 
	 * @return
	 */
	public Rest<T> getRest() {
		return new Rest<T>();
	}

	/**
	 * 這是個回調方法,線程的內容執行完後進行回調
	 * 
	 * @param result
	 */
	public abstract void call(T result);
}
 

不足之處:這裏只是針對一個Activity中有一個子線程操作的情況,當同時存在多個子線程的時候可以通過修改抽象call(T result,int which)來區分多個線程的返回值。

不過這又會引起新的問題:當多個線程的返回值的類型不一致的時候,泛型的作用就失效了,還是要進行強制類型轉換。

 這個設計還沒有正式用在我的項目中,這還都在測試階段,下一步我會試着去掉泛型,並添加對多個線程的支持。


改進方案參考:

android異步處理Handler+Thread使用進階(三)



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章