多界面 资源异步加载收尾总结

发布时间:2014-10-22 18:24:11编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"多界面 资源异步加载收尾总结",主要涉及到多界面 资源异步加载收尾总结方面的内容,对于多界面 资源异步加载收尾总结感兴趣的同学可以参考一下。

    来公司 开始接手 的项目涉及到多子界面  大量图片的异步加载。经过接近8个月的不断完善,达到了让自己满意的效果。现在对一块进行阶段性的总结.    个人不善言辞,所以我会贴出部分代码让大家能更好的理解相关内容和知识,说白了很简单,但对于初学者来说也是不太容易想到的。    主界面 +Viewpager + 7个子界面     7 个子界面放到 Viewpager 内 可以滑动进行显示。      每个子界面都是继存 Activity 类来实现   下面 贴 一个子界面在创建时候要做的事情。                 setContentView(R.layout.app_main); mAppTask = new AppTask(); boolean mFlag = ImageLoadThreadManager.getInstance().isAppFlag(); ThreadUtils.getInstance().addRunnable(mAppTask, mFlag);       mFlag 主要判断当前 子界面是否第一个加载 true :第一个加载,false 不第一个加载。       mAppTask 是一个Runnable 的实现者。     下面的这个类比较重要 主要负责接收 Runnable 任务 并添加到队列。然后启动一个线程予以执行.这样做的好处是减少线程的启动。提交程序运行速度。     当进入主界面时就不会因为大量的线程启动而导致界面卡顿。   最新版本 : 利用Android 的 Looper handler Message    来做。       /** * 负责资料传输 资源的异步加载 *  * @author DYL *  */    static final class ExeCutors implements Runnable { private LinkedList<BaseTask> mActivityTaskList = null; // 这个是各个子界面资源数据加载线程列表 private Thread mThread = null; public ExeCutors() { if (mActivityTaskList == null) { mActivityTaskList = new LinkedList<BaseTask>(); } if (mThread == null) { mThread = new Thread(this); } } private boolean mShutDown = false; public void shutdown() { mShutDown = true; if (Thread.currentThread() != mThread && mThread.isAlive()) try { mThread.join(); } catch (InterruptedException e) { e.printStackTrace(); } mThread = null; clear(); } private void clear() { mActivityTaskList.clear(); mActivityTaskList = null; } private boolean mHasRun = false; private void start() { if (!mHasRun && mExeTaskCount == 7) { mHasRun = true; mThread.start(); } } public void executor(BaseTask r, boolean isExeAnon) { if (isExeAnon) mActivityTaskList.addFirst(r); else mActivityTaskList.addLast(r); mExeTaskCount++; start(); // 启动 } private int mExeTaskCount; @Override public void run() { // 循环执行任务 while (!mShutDown) { if (mActivityTaskList.size() > 0) { BaseTask r = mActivityTaskList.getFirst(); if (!r.ismIsRun()) { r.setmIsRun(true); r.run(); mActivityTaskList.remove(r); mExeTaskCount--; } } // 执行任务完毕结束循环 if (mExeTaskCount == 0) break; } } }     当各个子界面的 异步任务添加到队列并顺序执行后,下面 贴一下图片异步加载的工具类。主要用到了java线程池。     添加到线程池应该是有序的 ,但还是做了线程同步,这可能有点影响程序执行效率。 /**  * 资源加载工具 并发 或者串行 5个线程并发执行 使用线程池,或者不使用. 每个界面自己持有线程池 或者共用一个。 最开始的时候界面有点卡.  *   *   * @author DYL  *   */ public class ImageLoadThreadManager { private Tool mLoadTool; // 一个 private boolean mAppFlag = true; public static class TempTool { public static String tempName = null; public static String getTempName() { return tempName; } public static void setTempName(String tempName) { TempTool.tempName = tempName; } } private Object mObject = new Object(); public Tool getTool() { synchronized (mObject) { if (mLoadTool == null) mLoadTool = new Tool(); } return mLoadTool; } private ExecutorService mExecutor; public synchronized void addRunnable(Runnable r) { if (mExecutor == null) mExecutor = Executors.newFixedThreadPool(1); mExecutor.execute(r); } public synchronized void removeRunnable(Runnable r) { if (mExecutor != null) ((ThreadPoolExecutor) mExecutor).remove(r); } /* * 判断是否先加载 */ public boolean isAppFlag() { return mAppFlag; } /** * 二维码识别帮助工具 *  * @author dyl *  */ public static class BarCodeTool { private final String prefix = "#"; // 含有这个标志说明你扫描的是非热点 private boolean mIsscanAp = true; // 是否扫描的热点 /** * 此方法只有一处调用,修改请注意 拿到 变量值后马上置为初始值 *  * @return */ public boolean isScanAp() { boolean temp = mIsscanAp ? true : false; if (!temp) mIsscanAp = true; return temp; } public String CreateSSID(String SSID) { return prefix + SSID; } static BarCodeTool bt; private BarCodeTool() { } private static BarCodeTool getmInstance() { synchronized (BarCodeTool.class) { if (bt == null) bt = new BarCodeTool(); } return bt; } public String cutStr(String source) { if (source.startsWith(prefix)) { mIsscanAp = false; return source.substring(source.indexOf(prefix) + 1); } else mIsscanAp = true; return source; } public static BarCodeTool getInstance() { if (bt == null) return getmInstance(); return bt; } public static void close() { bt = null; } /* * 判断是不是热点的SSID */ public boolean isSSID(String scanResult) { if (scanResult != null) { if (scanResult.startsWith(MyConstants.SSID) || scanResult.startsWith(prefix) || scanResult.startsWith(MyConstants.NFC_CREATE_AP)) return true; } return false; } } private boolean mHistoryFlag; public boolean isHistoryFlag() { return mHistoryFlag; } public void setFristStart(boolean appBool, boolean historyBool) { this.mAppFlag = appBool; this.mHistoryFlag = historyBool; if (!(appBool ^ historyBool)) { Log.e("Tools", "参数传入有误"); } } private static ImageLoadThreadManager imgloadmanager; public static ImageLoadThreadManager getInstance() { if (imgloadmanager == null) return getmInstance(); return imgloadmanager; } private ImageLoadThreadManager() { } private static ImageLoadThreadManager getmInstance() { synchronized (ImageLoadThreadManager.class) { if (imgloadmanager == null) imgloadmanager = new ImageLoadThreadManager(); } return imgloadmanager; } public void clear() { if (mLoadTool != null) { mLoadTool.shutDown(); mLoadTool = null; } closeSelf(); } private static void closeSelf() { synchronized (ImageLoadThreadManager.class) { if (imgloadmanager != null) { imgloadmanager.mLoadTool = null; imgloadmanager.mExecutor = null; imgloadmanager = null; } } } public static final class Tool { private final ExecutorService mThreadPool; private Tool() { /** * 1个线程去加载图片 可以通过调节数量来微调界面加载效果 */ mThreadPool = Executors.newFixedThreadPool(1); } public synchronized void addThread(Runnable r) { mThreadPool.execute(r); } public synchronized void removeThread(Runnable r) { /** * 从执行程序的内部队列中移除此任务(如果存在),从而如果尚未开始,则其不再运行, 如果已经删除则返回true */ ((ThreadPoolExecutor) mThreadPool).remove(r); } public synchronized void shutDown() { /** * 试图停止所有正在执行的活动任务, 暂停处理正在等待的任务,并返回等待执行的任务列表。 */ mThreadPool.shutdownNow(); ((ThreadPoolExecutor) mThreadPool).purge(); } public synchronized void cancelAllTask() { ((ThreadPoolExecutor) mThreadPool).getQueue().clear(); } } } 然后我要说的是图片的内存缓存 这里我贴出工具类。 /**  *   * 内存缓存技术  *   * @author dyl  *   */ public class LruCacheUtils { private LruCacheUtils() { if (mMemoryCache == null) mMemoryCache = new LruCache<String, Bitmap>( MyConstants.MAXMEMONRY / 8) { @Override protected int sizeOf(String key, Bitmap bitmap) { // 重写此方法来衡量每张图片的大小,默认返回图片数量。 return bitmap.getRowBytes() * bitmap.getHeight() / 1024; } @Override protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) { super.entryRemoved(evicted, key, oldValue, newValue); // 硬引用缓存区满,将一个最不经常使用的oldvalue推入到软引用缓存区 // 可以在这里进行bitmap的回收工作,前提是你保证bitmap不再被使用 if (oldValue != null) { if (mIsQuit && !oldValue.isRecycled()) oldValue.recycle(); oldValue = null; } } }; } private LruCache<String, Bitmap> mMemoryCache; private static LruCacheUtils cacheUtils; private static final String TAG = "CacheUtils"; private boolean mIsQuit; // 是否退出程序 private static LruCacheUtils getmInstance() { synchronized (LruCacheUtils.class) { if (cacheUtils == null) { cacheUtils = new LruCacheUtils(); } } return cacheUtils; } public static LruCacheUtils getInstance() { if (cacheUtils == null) return getmInstance(); return cacheUtils; } private static LruCacheUtils instance() { return cacheUtils; } public static void close() { synchronized (LruCacheUtils.class) { if (instance() != null) { cacheUtils.clearCache(); cacheUtils = null; } } } public synchronized void clearCache() { if (mMemoryCache.size() > 0) { mIsQuit = true; mMemoryCache.evictAll(); } } public synchronized void addBitmapToCache(String key, Bitmap bitmap) { if (mMemoryCache.get(key) == null) { if (key != null && bitmap != null) mMemoryCache.put(key, bitmap); } else Log.e(TAG, "the res is aready exits key:" + key); } public synchronized Bitmap getBitmapFromMemCache(String key) { if (key != null) { Bitmap bm; bm = mMemoryCache.get(key); return bm; } return null; } public synchronized void removeImageCache(String key) { if (key != null) { mMemoryCache.remove(key); } } }     最后说一下 对于过大的图片 进行缩放处理 然后在添加到 缓存,不然你的应用的内存会伤不起的。     强调一点: 不要以为应用的图标不大就不做缩放处理, 刚开始我也是忽略了应用图标的缩放处理,以为一个图标才几KB 后来实践证明我错了,做了缩放处理后足足节省了    10 M的内存大大提高了程序的性能.     最后在强调一点 慎用 线程同步 如果没有必要 就不要做线程同步。因为同步会降低程序的执行效率。这点需要好好考虑。                 


上一篇:HDU-2222 Keyword Search
下一篇:针对IE的CSS hack 全面 实用

相关文章

相关评论

本站评论功能暂时取消,后续此功能例行通知。

一、不得利用本站危害国家安全、泄露国家秘密,不得侵犯国家社会集体的和公民的合法权益,不得利用本站制作、复制和传播不法有害信息!

二、互相尊重,对自己的言论和行为负责。

好贷网好贷款