又优化了一下Android(安卓)ListView 异步加载图片(续)
16lz
2021-01-26
之前发表过一篇文章: 又优化了一下 Android ListView 异步加载图片
大家反应还行,不过普遍爆出new Thread太多会导致性能和资源浪费的问题,我想了一下的确如此,有人说用AsyncTask会更好点,因为实现的原理是线程池,肯定是比new Thread强,这个我也没有考证,后来根据自己的一套做了一些修改,只是一直没发出来,然后有些同学线下又找我要修改后的源码,我就索性把我修改的发出来给大家分享一下。
其实改动不大,就是把之前的new Thread改成了 Handler Looper Thread的模式,这样在第一次滑动的时候就进入了wait状态,又因为handler里面的runnable是队列执行的,所以handler一直在添加的runnable也在等待,这样就避免了多次new thread的问题,从头到尾就只有一个thread,别的不多说,看修改后的代码。
源码我就不上传了,就添加了一个类,修改了一个类:
package cindy.android.util;import android.os.Handler;import android.os.Looper;import android.os.Message;public class RunInOtherThread { private static final String LOG_TAG = "RunInOtherThread"; private LooperThread localThread = new LooperThread(); private boolean isRunning = true; public Handler getHandler(){ return localThread.getHandler(); } private class LooperThread extends Thread { private Handler mHandler; public void run() { Looper.prepare(); mHandler = new Handler() { public void handleMessage(Message msg) { onReceiveMessage(msg.what); } }; Looper.loop(); } Handler getHandler(){ return mHandler; } } public void start(){ localThread.start(); } public void quit(){ localThread.getHandler().getLooper().quit(); } public void sendMessage(int what){ getHandler().sendEmptyMessage(what); } public Thread getThread(){ return localThread; } public void onReceiveMessage(int what){}; }
package cindy.android.util;import java.io.DataInputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.lang.ref.SoftReference;import java.net.URL;import java.util.HashMap;import cindy.android.debug.DebugUtil;import android.graphics.drawable.Drawable;import android.os.Environment;import android.os.Handler;public class SyncImageLoader {private Object lock = new Object();private boolean mAllowLoad = true;private boolean firstLoad = true;private int mStartLoadLimit = 0;private int mStopLoadLimit = 0;final Handler handler = new Handler();private HashMap<String, SoftReference<Drawable>> imageCache = new HashMap<String, SoftReference<Drawable>>();RunInOtherThread runInOutherThread;public SyncImageLoader() {super();runInOutherThread = new RunInOtherThread();runInOutherThread.start();}public interface OnImageLoadListener {public void onImageLoad(Integer t, Drawable drawable);public void onError(Integer t);}public void setLoadLimit(int startLoadLimit, int stopLoadLimit) {if (startLoadLimit > stopLoadLimit) {return;}mStartLoadLimit = startLoadLimit;mStopLoadLimit = stopLoadLimit;}public void restore() {mAllowLoad = true;firstLoad = true;}public void lock() {mAllowLoad = false;firstLoad = false;}public void unlock() {mAllowLoad = true;synchronized (lock) {lock.notifyAll();}}public void loadImage(Integer t, String imageUrl,OnImageLoadListener listener) {final OnImageLoadListener mListener = listener;final String mImageUrl = imageUrl;final Integer mt = t;runInOutherThread.getHandler().post(new Runnable() {@Overridepublic void run() {if (!mAllowLoad) {synchronized (lock) {try {DebugUtil.debug("wait start.....");lock.wait();DebugUtil.debug("wait end.....");} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}if (mAllowLoad && firstLoad) {loadImage(mImageUrl, mt, mListener);}if (mAllowLoad && mt <= mStopLoadLimit && mt >= mStartLoadLimit) {loadImage(mImageUrl, mt, mListener);}}});}private void loadImage(final String mImageUrl, final Integer mt,final OnImageLoadListener mListener) {if (imageCache.containsKey(mImageUrl)) {SoftReference<Drawable> softReference = imageCache.get(mImageUrl);final Drawable d = softReference.get();if (d != null) {handler.post(new Runnable() {@Overridepublic void run() {if (mAllowLoad) {mListener.onImageLoad(mt, d);}}});return;}}try {final Drawable d = loadImageFromUrl(mImageUrl);if (d != null) {imageCache.put(mImageUrl, new SoftReference<Drawable>(d));}handler.post(new Runnable() {@Overridepublic void run() {if (mAllowLoad) {mListener.onImageLoad(mt, d);}}});} catch (IOException e) {handler.post(new Runnable() {@Overridepublic void run() {mListener.onError(mt);}});e.printStackTrace();}}public static Drawable loadImageFromUrl(String url) throws IOException {//DebugUtil.debug(url);if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {File f = new File(Environment.getExternalStorageDirectory()+ "/TestSyncListView/" + MD5.getMD5(url));if (f.exists()) {FileInputStream fis = new FileInputStream(f);Drawable d = Drawable.createFromStream(fis, "src");return d;}URL m = new URL(url);InputStream i = (InputStream) m.getContent();DataInputStream in = new DataInputStream(i);FileOutputStream out = new FileOutputStream(f);byte[] buffer = new byte[1024];int byteread = 0;while ((byteread = in.read(buffer)) != -1) {out.write(buffer, 0, byteread);}in.close();out.close();Drawable d = Drawable.createFromStream(i, "src");return loadImageFromUrl(url);} else {URL m = new URL(url);InputStream i = (InputStream) m.getContent();Drawable d = Drawable.createFromStream(i, "src");return d;}}}
更多相关文章
- Activity的构成
- Android中TextView中添加的文本上下两行又重叠
- Android常用的一些服务demo源码
- Android新的网络请求框架volley源码解释及示例
- android init.rc 到底在哪里?
- Android中Fragment碎片解析
- 框架和流程——OkHttp 源码详解(一)
- 在Android中使用AspectJ进行切面编程的简易步骤
- Camera的学习,图片的保存(两种),获取手机图片以及图片信息修改(小的图