在上篇文章《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)來區分多個線程的返回值。
不過這又會引起新的問題:當多個線程的返回值的類型不一致的時候,泛型的作用就失效了,還是要進行強制類型轉換。
這個設計還沒有正式用在我的項目中,這還都在測試階段,下一步我會試着去掉泛型,並添加對多個線程的支持。
改進方案參考: