后天就是大年初一啦!提前祝大家2017年大吉大利!
步入正题
其实我们从网络上拉取(加载)一张图片很简单,随随便便几行代码搞定,那我们的图片拉取池的意义在什么地方呢?首先我们用于图片拉取的线程是可控的,也就是说可以随时取消。其次我们内部封装了一层线程池,保证了我们拉取的图片是有序的。对于如何得到拉取之后的图片,我采用的是接口回调,每拉取一次都会返回给调用者。
好,现在我们看代码。
public class ThreadPool {
private static ExecutorService exec;
private static ThreadPool threadPool;
public static ThreadPool getInstance(){
if(threadPool != null){
return threadPool;
}
synchronized (ThreadPool.class) {
if(threadPool == null){
threadPool = new ThreadPool();
}
}
return threadPool;
}
private ThreadPool(){
exec = Executors.newFixedThreadPool(1);
}
public ThreadListener exec(Runnable runnable){
Future<?> future = exec.submit(runnable);
ThreadListener listener = new ThreadListener(future);
return listener;
}
public static class ThreadListener{
private Future<?> f;
public ThreadListener(Future<?> future){
this.f = future;
}
//试图取消线程,返回true表示取消成功
public boolean cancle(){
return f.cancel(true);
}
//判断是否完成
public boolean isDone(){
return f.isDone();
}
}
}
这里使用单例模式对线程池进行了一层封装,注意这里我们并没有使用execute()方法,而是采用submit方法并返回一个Future对象,这样做的好处就是,我们可以控制线程,可以随时取消并且判断是否完成等等。
public interface Callback {
void getBitmap(Bitmap bitmap);
}
接口,用于返回bitmap。
public class LoadImage {
private ThreadPool.ThreadListener threadListener;
private String url;
private final int readTimeout = 8*1000;
private final int connectTimeout = 8*1000;
private final String requestMethod = "GET";
private InputStream inputStream;
private Callback callback;
public LoadImage(String url, Callback callback){
this.callback = callback;
ThreadPool threadPool = ThreadPool.getInstance();
this.url = url;
threadListener = threadPool.exec(new Runnable() {
@Override
public void run() {
runnableWorker();
}
});
}
private void runnableWorker(){
try {
URL mURL = new URL(url);
HttpURLConnection httpURLConnection = (HttpURLConnection) mURL.openConnection();
httpURLConnection.setRequestMethod(requestMethod);
httpURLConnection.setDoOutput(true);
httpURLConnection.setDoInput(true);
httpURLConnection.setReadTimeout(readTimeout);
httpURLConnection.setConnectTimeout(connectTimeout);
inputStream = httpURLConnection.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
callback.getBitmap(bitmap);
} catch (IOException e) {
callback.getBitmap(null);
} finally {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public boolean cancle(){
return threadListener.cancle();
}
public boolean isDone(){
return threadListener.isDone();
}
}
这里我们对接口、线程池以及网络拉取进行二次封装。现在核心的方法我们已经封装完毕,针对于不同的使用,我们可以再进行一层简单的封装调用。
使用就非常简单了:
new LoadImage("图片网址", new Callback() {
@Override
public void getBitmap(Bitmap bitmap) {
}
});
笔者能力有限,不足之处欢迎指出!