日本搞逼视频_黄色一级片免费在线观看_色99久久_性明星video另类hd_欧美77_综合在线视频

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > 綜合技術 > Android之打造自己加載高清大圖及瀑布流框架.解決錯位等問題.

Android之打造自己加載高清大圖及瀑布流框架.解決錯位等問題.

來源:程序員人生   發布時間:2016-03-21 08:58:22 閱讀次數:4530次

首先看效果圖以下:

 https://github.com/q422013/ImageLoader

本框架支持本地圖片和網絡圖片的獲得.采取LruCache算法,最少使用的最早釋放.有效的避免OOM,項目結構圖:

核心加載類在于ImageLoader.采取了TreadPool去做并發要求.UI處理采取Handler去管理,實現的思路類似于AsnycTask類.該類采取單例模式:

public static ImageLoader getInstance(Context context) { if (null == loader) { synchronized (ImageLoader.class) { if (null == loader) { loader = new ImageLoader(context, defThreadCount, mType); } } } return loader; } public static ImageLoader getInstance(Context context, int threadCount, Type type) { if (null == loader) { synchronized (ImageLoader.class) { if (null == loader) { loader = new ImageLoader(context, threadCount, type); } } } return loader; }

第1種類不需要配置線程池及加載方式.加載方式分為兩種:1.先進先加載,2.落后先加載. /** * 隊列調度模式 */ public enum Type { FIFO, LIFO }
工作線程中核心是用Loop去不斷的取消息,取到消息后就加入到線程池當中去履行,這樣減少了自己去保護輪訓,減少內存開消. //工作線程 mThread = new Thread() { @Override public void run() { Looper.prepare(); mPoolThreadHandler = new Handler() { @Override public void handleMessage(Message msg) { mThreadPool.execute(getTask()); try { mPoolSemaphore.acquire();//信號量 + 1 } catch (InterruptedException e) { e.printStackTrace(); } } }; mSemapHore.release();//初始化完成后信號量 ⑴ Looper.loop(); } };

從上面代碼可以看出PoolTreadHandler收到1個消息后會讓mThreadPool去履行1個任務,該任務通過getTask()方法取得1個Runnable對象,并且讓信號量增加表示,線程池中有1個任務了.

看看getTask()代碼很簡單,僅僅是將任務按不同的方式取出來:

/** * 獲得任務 * * @return */ private synchronized Runnable getTask() { if (0 < mTask.size()) { if (mType == Type.LIFO) return mTask.removeFirst(); else return mTask.removeLast(); } return null; }

真實的工作在于mTask去add,mTask是1個LinkedList類型的集合.所以核心在于方法Load() /** * 加載圖片 * * @param path * @param imageview */ public void load(final String path, final View view, final LoadListenerloadListener) { if (null == path) throw new RuntimeException("this path is null"); if (null == loadListener) throw new RuntimeException("this loadListener is null"); view.setTag(path); //1.從磁盤,2.從內存 if (null == mDisPlayHandler) mDisPlayHandler = new Handler() { @Override public void handleMessage(Message msg) { int code = msg.what; ViewBeanHolder holder = (ViewBeanHolder) msg.obj; final View view = holder.view; Bitmap bm = holder.bitmap; String path = holder.path; switch (code) { case LOAD_SUCCESS://加載成功 if (view.getTag().toString().equals(path)) { loadListener.LoadSuccess(view, bm, path); if (isNeedAnim) new LoadAnimCore(view); } break; case LOAD_ING://加載中 if (view.getTag().toString().equals(path)) { loadListener.Loading(view, path); } break; case LOAD_FAILE://加載失敗 if (view.getTag().toString().equals(path)) { loadListener.LoadError(view, path, null);//暫時消息為空 } break; } } }; addTask(path, view); }

其中view.setTag是為了避免錯亂.上面代碼可以看出來僅僅是用于callBack,核心的東西其實在addTask方法.我們看看addTask方法做了甚么事情: /** * 添加任務 * * @param path * @param view */ private synchronized void addTask(final String path, final View view) { Runnable runnable = new Runnable() { @Override public void run() { ViewBeanHolder holder = new ViewBeanHolder(); holder.view = view; holder.path = path; sendMsg(LOAD_ING, holder); //TODO 從內存中獲得 Bitmap bitmap = LruCacheUtils.getInstance().get(path); if (null == bitmap) { //TODO 從磁盤中獲得 String tempPath = getImageFromDiskUrl(path); if (null != tempPath) { bitmap = decodeSampledBitmapFromResource(tempPath, (ImageView)view); } else { if (null == bitmap) { // TODO 從網絡中獲得 bitmap = decodeSampledBitmapFromNetWork(path, (ImageView)view); } else { // TODO 失敗 sendMsg(LOAD_FAILE, holder); } } } //加載成功 if (null != bitmap) { LruCacheUtils.getInstance().put(path, bitmap); holder.bitmap = bitmap;//唯1的 sendMsg(LOAD_SUCCESS, holder); } else { //加載失敗 sendMsg(LOAD_FAILE, holder); } } }; if (null == mPoolThreadHandler) { try { mSemapHore.acquire(); } catch (InterruptedException e) { e.printStackTrace(); } } mTask.add(runnable); mPoolThreadHandler.sendEmptyMessage(0x1000); mPoolSemaphore.release();//信號量 ⑴ }

緩存策略:先從內存中獲得,如果沒有獲得到,就從磁盤獲得,磁盤也沒有獲得到,那就從網絡獲得.最后并將該bitmap設置到內存緩存,假象:如果設置非常多的bitmap到內存緩存中肯定會讓內存占滿致使OOM,所以便采取了google推薦使用的LruCache緩存算法.該算法可以實現固定內存加載,并且最近少使用的會被內存回收掉.

然后在MainActivity中可使用以下:

ImageLoader.getInstance(MainActivity.this, 3, ImageLoader.Type.LIFO).load(IMAGES[position], holder.imageView);

上面加載方式是直接交給內部處理.圖片默許加載RGB_565. ImageLoader.getInstance(MainActivity.this, 3, ImageLoader.Type.LIFO).load(IMAGES[position], holder.imageView, new LoadListener() { @Override publicvoid Loading(View view, String path) { } @Override publicvoid LoadSuccess(View view, Bitmap bitmap, String path) { ((ImageView) view).setImageBitmap(bitmap); } @Override publicvoid LoadError(View view, String path, String errorMsg) { Log.d("Tanck","加載失敗:"+path); ((ImageView)view).setImageResource(R.mipmap.ic_launcher); } });

采取幾個加載配置方式內存對照:

RGB_565:

約11.31MB,效果以下:

ARGB_8888:

約12.86MB效果圖以下:

可以看出差別不是很大.

但是ARGB_4444使用內存和RGB_565相近,但是效果很差,效果圖以下:


生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 欧美日韩亚 | 天堂av中文| 国产伦精品一区二区三 | 麻豆最新网址 | 亚洲精品欧美一区二区三区 | www.怡红院.com| 国产一区福利 | 久久99精品久久久久久琪琪 | 亚洲自拍偷拍网站 | 国产一区二区三区四区五区美女 | 国产精品久久久久久久久久东京 | 国产精品久久网站 | 日本欧美三级 | 成人福利免费在线观看 | 久热中文 | 欧美日韩精品一区二区公司 | 免费网站黄 | 91成人在线视频 | 国产一二三区免费视频 | 欧美日韩一区不卡 | 网友自拍第一页 | 色五月激情综合网 | 国产精品久久久久久久久久久久 | 国产伦精品一区二区 | 国产区在线 | 片黄在线观看 | 蜜桃永久免费 | 九九视频在线 | 久久久久久国产精品免费免费 | 日韩欧美一区二区三区久久婷婷 | 日韩精品久久久久 | av看片 | 中文字幕一区二区在线播放 | 久久精品亚洲一区二区三区浴池 | 黄色小视频免费 | 国产影院av | a在线免费观看 | 国内精品视频在线播放 | 国产精品免费一区二区三区都可以 | 国产精品麻豆一区二区 | 色综合第一页 |