设为首页 加入收藏

TOP

Android异步任务(AsyncTask)的设计思想(一)
2014-11-24 01:09:15 来源: 作者: 【 】 浏览:20
Tags:Android 异步 任务 AsyncTask 设计思想

这里说有设计思想是我根据查看Android源代码提炼出来的代码逻辑,所以不会跟Google工程师的原始设计思想100%符合(也有可能是0%),但是本文一定可以帮助你理解AsyncTask,也可能有一些你以前没有发现的内容。


大家都知道,Android的主线程(又叫UI线程,线程ID为1)有一些限制策略,使得主线程有些事做不了,比如访问网络就不允许,否则就是报,但在2.3之后的版本,你可以通过添加以下代码更改其限制策略,从而强制使得主线程可以访问网络:


if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}


不过StrictMode是一个开发工具主要用于侦测主线程中的磁盘和网络访问,而不是让你做这“坏”事,其实Android这样限制是有好处的,强制让开发者重视用户体验,一个反面例子是Windows,主线程里什么都可以做,一些很懒的开发者就把所有任务放到主线程里,使得线程经常好卡,比如编辑器UE或Notepad++打开了一个网络上(如samba服务器)的文件,如果突然网络中断了,那你的整个编辑器都卡住,要等好久才会有反应,不过我不确定那是不是因为主线程里访问了网络,不过Windows经常因为这个原因卡。还有一个正面例子是iOS,极其注意响应速度,所以当有用户输入事件时,其内核都有相应的调度,从而优先响应用户操作。


还是回到正题,就是因为主线程的这些限制使开发者不得不写多个线程,当然,你也可以不用AsyncTask,不过你不用也避免不了多线程,如果你不用,就是可能要用Handler和Thread了,我想很多人初学的时候就是那么干的,包括我,因为那时很有可能还没有发现有这个类,于是就经常写Handler和Thread的了,写着写着就发现有一些代码是相同的,你写的Handler和Thread匿名类肯定是重复代码,如下:


final Handler handler = new Handler() {
public void handleMessage(Message msg) {
System.out.println("The hard have done!");
// ... front end code
}
};
new Thread() {
public void run() {
doHardWork();
handler.sendEmptyMessage(0);
}


private void doHardWork() {
// ... back end code
}
}.start();


你可能想到要复用这些代码,当然,你可以通过Copy的方式来复用这段代码,用的时候只要在省略号处写入你的代码就可以了,但更好的复用是将其用一个类封装起来,好吧,那我们就简单的封装一下吧,于是,就变成了这样:


public class HandlerAndThread {
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
System.out.println("The hard have done!");
//...
}
};

public void doInBackground() {
new Thread() {
public void run() {
doHardWork();
handler.sendEmptyMessage(0);
}



private void doHardWork() {
// ...
}
};
}

}


这样好像还不行,因为无法告诉后台线程做什么事,做完了也不知道通知,要复用还是得Copy代码,我们可以加两个方法,一个在前台调用一个在后台调用,只要定义一个新类就可以实现复用,于是代码变成这样:


public class HandlerAndThread {
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
System.out.println("The hard have done!");
runInFrontend(); // added
}
};

public void doInBackground() {
new Thread() {
public void run() {
doHardWork();
handler.sendEmptyMessage(0);
}


private void doHardWork() {
runInBackend(); //added
}
};
}

//added
protected void runInBackend() {
}

//added
protected void runInFrontend() {
}
}


一个可复用的类就出炉了,我们写一个子类,并用一个Activity来调用一下吧:


public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);


new SubHandlerAndThread().doInBackground();
}

class SubHandlerAndThread extends HandlerAndThread {
protected void runInBackend() {
try {
Thread.sleep(10 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

protected void runInFrontend() {
System.out.println("Task has been done");
}
}
}


这样是不是比直接写Thread和Handler简洁了许多呢,这里我是用sleep来模似长时间事务的,如果在真实的环境中,我们可能是要下载,如果是下载,我们可能希望传入个下载地址的参数到后台线程,来让他按我们的需要下载,我们给加doInBackground方法加一个参数,于是HandlerAndThread类的代码就变成这样:


public class HandlerAndThread {
...

public void doInBackground(final String url) { // adde

首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Emacs开发Java之使用 下一篇2013年阿里算法笔试题解题报告

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: