前言
在写自定义ImageLoader的时候,需要从网络上下载图片,联网操作需要使用线程。而同时用线程池管理线程的创建和使用,避免一次创建太多线程。
自己实现图片加载框架
说实话,有点懵,因为平常写学校里的东西,几乎不考虑多线程的。
花了很久的时间,看了很多博客,感觉都说不清楚。
最终找到的参考资料为:《Android开发艺术探索》:
第十章:Android的消息机制
第十一章:Android的线程和线程池
线程
在《Andorid开发艺术探索》第十一章中,解释到:
Android的线程分为主线程和子线程,主线程又叫UI线程,主要用于处理界面交互相关的逻辑。而除了主线程外的所有线程都叫做子线程,子线程一般用于执行耗时操作。
除了Thread本身以外,在Android中可以扮演线程的角色还有很多,比如AsyncTask
和IntentService
,同时HandlerThread
也是一种特殊的线程。尽管他们的表现方式 有别于传动的线程,但是他们的本质仍然是传统线程。‘’对
AsyncTask
来说,它的底层用到了线程池和Handler,主要为了方便开发者在子线程中更新UI
对于IntentService
和HandlerThread
来说,它们的底层则直接使用了线程。HandlerThread是一种具有消息循环的线程,在它的内部可以使用Handler
如何创建新线程
Android中启动线程的几种方式
而我是这样用的
for (int i = 0; i < 10; i++) {
new Thread(() -> Log.d(TAG, "run: 1")).start();
new Thread(() -> Log.d(TAG, "run: 2")).start();
}
log如下:
...
06-05 16:27:09.500 5841-5977/com.example.myimageloader D/myThreadActivity: run: 2
06-05 16:27:09.501 5841-5982/com.example.myimageloader D/myThreadActivity: run: 1
06-05 16:27:09.502 5841-5984/com.example.myimageloader D/myThreadActivity: run: 1
06-05 16:27:09.504 5841-5980/com.example.myimageloader D/myThreadActivity: run: 1
06-05 16:27:09.504 5841-5978/com.example.myimageloader D/myThreadActivity: run: 1
06-05 16:27:09.508 5841-5986/com.example.myimageloader D/myThreadActivity: run: 1
06-05 16:27:09.514 5841-5985/com.example.myimageloader D/myThreadActivity: run: 2
06-05 16:27:09.516 5841-5987/com.example.myimageloader D/myThreadActivity: run: 2
使用AsyncTask、IntentService和HandlerThread
Android的消息机制
在《Andorid开发艺术探索》第十章中:
从开发的角度来说,Handler是Android消息机制的上层接口,这使得开发过程只需要和Handler交互即可。Handler的使用过程很简单,通过它可以轻松的将一个任务切换到Handler所在的线程中去执行。
更新UI仅仅是Handler的一个特殊的使用场景
handler的使用方法
//在主线程创建一个Handler对象。
//重写Handler的handleMessage方法,这个就是接收并处理消息的方法。
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
//msg就是子线程发送过来的消息。
}
};
//开启一个子线程
new Thread(new Runnable() {
@Override
public void run() {
//在子线程发送一个消息。
Message msg = new Message();
handler.sendMessage(msg);
}
}).start();
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
Log.i(TAG,"Handler 发送过来的消息是:" + msg.obj);
}
};
new Thread(new Runnable() {
@Override
public void run() {
Message msg = new Message();
msg.obj = "我是消息数据";
handler.sendMessage(msg);
}
}).start();
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
Log.i(TAG, "第一个消息是:" + msg.obj);
break;
case 2:
Log.i(TAG, "第二个消息是:" + msg.obj);
break;
}
}
};
new Thread(new Runnable() {
@Override
public void run() {
Message msg1 = new Message();
msg1.obj = "第一个消息";
msg1.what = 1;
handler.sendMessage(msg1);
Message msg2 = new Message();
msg2.obj = "第二个消息";
msg2.what = 2;
handler.sendMessage(msg2);
}
}).start();
上面就是一个简单的Handler使用例子。我们在主线程创建一个Handler,他的handleMessage()方法是运行在主线程的,当我们在子线程发送一个消息的时候,handleMessage()会接收到消息,这样我们就把消息由子线程发送到了主线程。