在上篇文章《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)来区分多个线程的返回值。
不过这又会引起新的问题:当多个线程的返回值的类型不一致的时候,泛型的作用就失效了,还是要进行强制类型转换。
这个设计还没有正式用在我的项目中,这还都在测试阶段,下一步我会试着去掉泛型,并添加对多个线程的支持。
改进方案参考: