Android Looper,handler,HandlerThread

1

上回书说道,掌柜的饿了,叫大厨做饭去了;但一家客栈如果不冷清的话,就会有很多客人;跑堂的小二问完客观,记下来,会跟大厨喊:两斤酱牛肉,两斤烤鸭;至于茶水,跑堂的自己端过去就行了;那掌柜的是不是得记账啊;所以更可能的情况是小二用纸笔记下来,一份送到掌柜的,一份送到大厨那里;掌柜的可能就直接收起来,等晚些时候记账也行,大厨就不一样了,那就是铁定的任务了;看完这个消息,做个鱼香肉丝,再看哪个,做个清蒸红薯之类的。。。
相关访问,一定要看的;
http://www.cnblogs.com/codingmyworld/archive/2011/09/14/2174255.html

2

主程序:可以看成是客栈的整个大堂,人来人往,小二忙的不亦乐乎
线程:大厨做饭得有锅啊;但是此时的锅只能做一道菜,做完就不能用了,大厨就把它藏起来了;之后来的n多单子不接受;
looper:掌柜的一看,说这不行啊,加钱!让锅一直待在厨房,有单子就炒菜,没有就等着单子的到来;于是线程就升级为循环线程;
Message:小二递过来的单子
MessageQueue:虽然大厨是处于循环工作状态,但是那么多单子总得有个序列吧,此处将单子排序,大厨就可以按照次序
Handler:大厨,关键人物,小二将单子交给大厨,到了厨房,大厨就将其放入消息队列,到了的话,就炒菜;
那假如客栈大,厨师好多,一个相同的消息队列 不同的菜交给不同厨师,一个厨师可以对应好几道菜,不过的按照顺序吵;

3

1
2
3
public class ThumbnailDownloader<Token> extends HandlerThread { //线程
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class PhotoGallleryFargment extends Fragment { //主线程
ThumbnailDownloader<ImageView> thumbnailDownloader;
@Override
public void onCreate(Bundle s)
{
thumbnailDownloader.start(); //启动线程
thumbnailDownloader.getLooper(); //升级线程,与looper进行关联
Log.i(TAG,"Background thread started");
} @Override
public void onDestroy() //别忘了关闭线程
{
super.onDestroy();
thumbnailDownloader.quit();
Log.i(TAG,"background thread destroy");
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class ThumbnailDownloader<Token> extends HandlerThread {
private static final String TAG = "ThumbnailDownloader";
private static final int MESSAGE_DOWNLOAD=0;
Handler handler;
Map<Token,String> requestMap = Collections.synchronizedMap(new HashMap<Token, String>());
@SuppressLint("HandlerLeak")
@Override
protected void onLooperPrepared() //looper的准备方法哦,调用于第一次消息队列检查之前
{
handler = new Handler() //创建handler
{
@Override
public void handleMessage(Message msg)//处理message 由于handler本就创建于looerPrepared ,就省去消息发送的环节;
{
if(msg.what == MESSAGE_DOWNLOAD)
{
@SuppressWarnings("unchecked")
Token token =(Token)msg.obj;
Log.i(TAG,"got to request for url :"+ requestMap.get(token));
handleRequest(token);
}
}
};
}
public void queueThumbnail(Token token ,String url)
{
Log.i(TAG,"Got to url :"+url);
requestMap.put(token,url);
handler
.obtainMessage(MESSAGE_DOWNLOAD,token)
.sendToTarget();
}
private void handleRequest(final Token token) //处理发送过来的token,完成
{....}
public void cleanQueue()
{....}
}
现在完成的是什么呢?大厨自己想吃东西了,所以就自己在消息队列中加了一个单子,自己做;

4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Override //主程序将handler传递给线程,
public void onCreate(Bundle s)
{
super.onCreate(s);
setRetainInstance(true);
new FetchItemsTask().execute();
thumbnailDownloader = new ThumbnailDownloader<ImageView>(new Handler());//Handler()方法就近关联looper,所以关联至主程序的looper;将其通过构造函数传递给线程
thumbnailDownloader.setListener(new ThumbnailDownloader.Listener<ImageView>() {...通过listener,
}
});
thumbnailDownloader.start();
thumbnailDownloader.getLooper();
}
线程添加如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Handler responsehandler;
ThumbnailDownloader.Listener<Token> mlistener;
public interface Listener<Token>
{
void onThumbnailDownloaded(Token token,Bitmap thumbnail);
}
public void setListener(Listener<Token> listener)
{
mlistener=listener;
}
public ThumbnailDownloader(Handler responsehandler)//构造函数
{
super(TAG);
this.responsehandler=responsehandler;
}
private void handleRequest(final Token token)
{
....
responsehandler.post(new Runnable() { //传说中的handler的信息发送;由于responhandler关联到的是主程序的looper,所以信息也自然发送到主线程,于是我们就在线程中改变了主线程的UI 哈哈;
public void run() {
if(requestMap.get(token)!=url)
return;
requestMap.remove(token);
mlistener.onThumbnailDownloaded(token,bitmap);
}
});
}