首页 > 其他 > 详细

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

时间:2014-02-14 03:50:54      阅读:447      评论:0      收藏:0      [点我收藏+]

    来公司 开始接手 的项目涉及到多子界面  大量图片的异步加载。经过接近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 任务 并添加到队列。然后启动一个线程予以执行.这样做的好处是减少线程的启动。提交程序运行速度。

    当进入主界面时就不会因为大量的线程启动而导致界面卡顿。



      /**
* 负责资料传输 资源的异步加载

* @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的内存大大提高了程序的性能.

    最后在强调一点 慎用 线程同步 如果没有必要 就不要做线程同步。因为同步会降低程序的执行效率。这点需要好好考虑。


      

  



  

 

 




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

原文:http://blog.csdn.net/hulongkao1/article/details/19150935

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!