之前挺喜欢用AsyncTask 进行异步加载的,但是突然今天遇到一个很无语的问题。在2.3 ,2.6等android手机系统里面,用AysncTask时没有任何问题。但是在4.0以上的,4.2的,结果就悲催了,数据无法加载,认真一查看,发现dobackground函数 压根没有执行。纳闷了半天。。。而且我也是指执行了
然后开始查看资料,发现AsyncTask 在4.0后,里面的线程池变成了一个SingleThreadExecutor。每次只能够执行一个线程。所以有时候,多个AsyncTask在运行的时候,每次线程池里面只会有一个线程在运行,基本可以说是一个一个地执行。可以利用AsyncTask.executeOnExecutor 函数来自定义线程池,执行。这样就不会出问题了。
但是在2.3 等的时候,AsyncTask内部的线程池,能够同时执行5个线程。我猜想,可能是我程序里面的task太多,导致没法执行,部分加载必须等到前一个task执行完,才能执行,没法执行。这个问题也没有解决。不过我换了个解决的方式。自己写一个类似的加载方式。暂不成熟,仅供参考。我改成了另外一个方式。
public abstract class AbsAsyncTask<Params, Progress, Result>{
public AbsAsyncTask(){
}
private static final int PUBLISH_PROGRESS = 1;
private static final int POST_EXECUTE = 2;
private static final int PRE_EXECUTE = 3;
private Handler handler ;
public final void execute(final Params ...values){
handler = new Handler(){
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
// if(msg.what == id){
// }
switch (msg.what) {
case PUBLISH_PROGRESS:
onProgressUpdate((Progress)msg.obj);
break;
case POST_EXECUTE:
onPostExecute(result);
break;
case PRE_EXECUTE:
onPreExecute();
default:
break;
}
super.handleMessage(msg);
}
};
new Thread(){
@Override
public void run() {
Message msg1 =new Message();
msg1.what = PRE_EXECUTE;
handler.sendMessage(msg1);
result = doInBackground(values);
Message msg =new Message();
msg.what = POST_EXECUTE;
// setMsgId(msg);
handler.sendMessage(msg);
}
}.start();
}
private Result result = null;
/**
* 每个类的 msg.what 必须要不一样!
* @param msg
*/
// protected abstract void setMsgId(Message msg);
public void publishProgress(Progress ...values){
Message msg =new Message();
msg.what = PUBLISH_PROGRESS;
if(values.length>0){
msg.obj = values[0];
}
handler.sendMessage(msg);
}
protected void onPreExecute() {
}
protected void onProgressUpdate(Progress... values) {
}
protected Result doInBackground(Params... params) {
// TODO Auto-generated method stub
return null;
}
protected void onPostExecute(Result result) {
// TODO Auto-generated method stub
}
用原来的程序继承AsyncTask的,去继承这个类。然后程序就基本能够原封不动地执行了。额,估计上面的代码是有一些问题的。这里只是一个实现的方式,自己也可以在代码中像AsyncTask 一样,放一个线程池。每次执行的时候,执行一个runnable 。
但是我体会更多的是:
1.尽量将代码结构化,抽象化,有时候当你需要将代码重写使用新的方式去写的时候,你会感觉巨蛋疼。如果能够将相同的代码集中起来,尽量只用一份代码。这样修改起来,只需要修改那份代码就够了。尽量增加代码的重复利用率。尽量在程序中少使用两份一模一样的代码。
2.以前很长一段时间都不知道封装为何物,不知道它的价值在哪。今天算是体会到了。我在原来的代码中,只用到了AsyncTask的几个接口。其他的我都没有去用。然后将AsyncTask替换一下。将其内部实现修改一下。根本不会影响到其他部分的代码。
3.就想今天看《编程珠玑》看到的一句:Good programmers are a little bit lazy: they sit back and wait for an insight rather than rushing forward with their first idea. 不要急于修改bug,急于编码。洞察完代码,然后才去找一个最perfect,最有感觉的方式解决一个问题。