Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android仿最新6.2版本微信相冊

android仿最新6.2版本微信相冊

編輯:關於Android編程

仿微信相冊選擇圖片,查看大圖,寫的不太好,希望評論指出不足,諒解,先介紹一下我的基本思路

第一步獲取手機上的所有圖片路徑:

 

                Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                ContentResolver contentResolver = getContentResolver();
                //獲取jpeg和png格式的文件,並且按照時間進行倒序
                Cursor cursor = contentResolver.query(uri, null, MediaStore.Images.Media.MIME_TYPE + "=\"image/jpeg\" or " +
                        MediaStore.Images.Media.MIME_TYPE + "=\"image/png\"", null, MediaStore.Images.Media.DATE_MODIFIED+" desc");
                if (cursor != null){
                    while (cursor.moveToNext()){
                        //do something
                    }
                    handler.sendEmptyMessage(0);
                }

 

我的存儲格式

 

    /** 按時間排序的所有圖片list */
    private ArrayList allImages;
    /** 按目錄排序的所有圖片list */
    private ArrayList imageDirectories;
     /**
     * 一個文件夾中的圖片數據實體
     */
    private class SingleImageDirectories{
        /** 父目錄的路徑 */
        public String directoryPath;
        /** 目錄下的所有圖片實體 */
        public ImageDirectoryModel images;
    }

一個是全部圖片的存儲順序,第二個是按照目錄的圖片存儲順序

 

第二步,獲取到圖片之後,放入到gridview中進行顯示,但是BitmapFactory.decodeFile()函數會非常耗時,所以為了使得非常流暢的顯示圖片,創建一個類AlbumBitmapCacheHelper.class,用來異步加載圖片,

該類使用LruCache cache來緩存Bitmap,使得存儲圖片不會造成oom,我這裡設置cache的初始大小為1/4的運行時內存

然後使用ThreadPoolExecutor線程池來處理圖片的顯示,線程池大小應該設置適中

做完這兩件事情之後就可以用來加載圖片了,方法getBitmap用來講

        Bitmap bitmap = getBitmapFromCache(path, width, height);
        //如果能夠從緩存中獲取符合要求的圖片,則直接回調
        if (bitmap != null) {
        } else {
            //新建線程放入線程池去處理該圖片的顯示
        }
        return bitmap;

如果cache中找不到該圖片,則調用BitmapFactory.decodeFile()去加載圖片,加載圖片不能夠直接加載原圖,會造成OOM,所以要去處理壓縮比

 

                        BitmapFactory.Options options = new BitmapFactory.Options();
                        options.inJustDecodeBounds = true;
                        BitmapFactory.decodeFile(path, options);
                        options.inSampleSize = computeScale(options, width, height);
                        options.inJustDecodeBounds = false;
                        bitmap = BitmapFactory.decodeFile(path, options);
                        //獲取之後,放入緩存,以便下次繼續使用
                        if (bitmap != null && cache!=null) {
                            cache.put(path, bitmap);
                        }

方法computeScale()主要是計算圖片最小的壓縮比,

 


這樣在gridview中的getview方法中去調用AlbumBitmapCacheHelper.class的getBitmap方法即可, 但是這樣會有很多的問題:
一個問題就是圖片顯示會閃,這主要是由於getview的view的復用,解決方法就是使用settag方法
holder.iv_content.setTag(path);
將要顯示的Imageview的tag設置為需要顯示的圖片路徑,這樣在回調的時候使用方法gridView.findViewWithTag(path),找到這個imageview進行顯示,閃的問題就解決了

第二個問題就是加載速度很慢,拉的速度很快的情況下,圖片要很久才會加載出來,特別是很大的圖片,比如拍照和截圖的照片,
解決方法第一方案就是在AlbumBitmapCacheHelper類中維護一個ArrayList currentShowString,在getview方法中,如果該圖片要顯示,則直接將path加入到該list中,同時如果這個view的tag不為空,說明該view的原來的path是不需要顯示的,所以需要將這個path從list中刪除:

//優化顯示效果 if(holder.iv_content.getTag() != null) { String remove = (String) holder.iv_content.getTag(); AlbumBitmapCacheHelper.getInstance().removePathFromShowlist(remove); } AlbumBitmapCacheHelper.getInstance().addPathToShowlist(path);
這樣在線程池中的處理方式就是先查看需要顯示的path是否在list中,如果沒有在list中,則該線程直接關閉,如果在list中,則顯示該圖片

if (!currentShowString.contains(path)||cache==null) { return; }


第二個方案就是如果顯示的圖片很大,特別是拍照,截圖和解圖的圖片,decode有時會耗時幾秒中,微信顯示效果非常好,我自己想出來的處理的方式就是
***第一步,從應用的緩存temp目錄下取,如果取不到,
***第二步,計算圖片的壓縮比例samplesize,如果samplesize < 4,圖片的BitmapFactory.decodeFile()時間短,直接返回圖片,但是如果 samplesize > 4,執行第三步
***第三步則將壓縮後的圖片存入temp目錄下,以便下次快速取出這樣顯示圖片的效果就出來了,顯示的速度除了和微信一樣第一次大圖加載慢之外,之後的顯示就能很快了,

 

                     if (!new File(CommonUtil.getDataPath()).exists())
                        new File(CommonUtil.getDataPath()).mkdirs();
                    //臨時文件的文件名
                    String tempPath = CommonUtil.getDataPath() + hash + ".temp";
                    //如果該文件存在
                    if (new File(tempPath).exists())
                        bitmap = BitmapFactory.decodeFile(tempPath);
                    ......
                    //第三步,如果縮放比例大於4,該圖的加載會非常慢,所以將該圖保存到臨時目錄下以便下次的快速加載
                        if (options.inSampleSize >= 4) {
                            try {
                                File file = new File(tempPath);
                                if (!file.exists())
                                    file.createNewFile();
                                FileOutputStream fos = new FileOutputStream(file);
                                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                                bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
                                fos.write(baos.toByteArray());
                                fos.flush();
                                fos.close();
                            } catch (FileNotFoundException e) {
                                e.printStackTrace();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }

問題就差不多解決了

第三步大圖的查看,大圖只要是使用的網上找的ZoomImageView+viewpagger的組合,但是使用這個出現的問題就是很容易OOM,沒辦法,我的處理方式就是在點進去大圖的時候

 

 

public void releaseHalfSizeCache() {
    cache.resize((int) (Runtime.getRuntime().maxMemory() / 1024 / 8));
}

直接將cache的大小變成原來的一半,因為查看大圖頁,加載一張大圖占用的內存就很大,這樣顯示效果頁還湊合,有別的方法,一定要留言告訴我

注意:大圖的查看由於需要通過intent傳遞數據,但是intent傳遞的數據大小不能太大,如果手機上有幾千張圖片,則數據量大小可能會超過intent所能傳遞的最大量,所以可以寫入一個公共的地方,內存,數據庫,文件都可以,

//TODO 這裡由於涉及到intent傳遞的數據不能太大的問題,所以如果需要,這裡要進行另外的處理,寫入到內存或者寫入到文件中  
intent.putExtra(PickBigImagesActivity.EXTRA_DATA, getAllImagesFromCurrentDirectory());

我暫時沒有處理~~

 

第四步就是圖片選擇完成之後,完成善後工作,將AlbumBitmapCacheHelper類中cache清空,差不多就這樣了,還有很多的小問題,比如圖片時間的顯示,具體大家看源碼

 


\ \

 

源碼下載點我

由於源碼是android studio的工程,所以不能直接導入eclipse,必須要手動拷貝文件,在這裡放出所有的文件,方便eclipse

\

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved