Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android 獲取本地圖片(二)

android 獲取本地圖片(二)

編輯:關於Android編程

鏈接上一篇博文

本篇博文接著講述本地圖片的獲取。
下面給出獲取本地圖片的異步線程類LoadLoacalPhotoCursorTask的代碼:

/**
* 獲取本地圖片的異步線程類
*/
public class LoadLoacalPhotoCursorTask extends AsyncTask

下面給出加載圖片的類ImageWorker的代碼:

/**
 * 手機本地圖片異步加載處理類
 * 圖片的加載性能影響很大,使用弱引用和軟引用
 * 緩存圖片,加快響應的速度,提高性能。
 */
public class ImageWorker {

    //這個值設置的是加載圖片的動畫效果的間隔時間,達到漸隱漸顯的效果
    private static final int FADE_IN_TIME = 200;

    private boolean mExitTasksEarly = false;//判斷圖片加載任務是否提前退出
    private boolean mPauseWork = false;//加載圖片線程是否掛起
    private final Object mPauseWorkLock = new Object();//鎖對象,這個鎖對象是為了判斷是否進行圖片的加載

    protected final Resources mResources;
    private final ContentResolver mContentResolver;//內容解析者
    private final BitmapFactory.Options mOptions;

    private final HashMap> bitmapCache = new HashMap>();//用於緩存圖片,每一個緩存的圖片對應一個Long類型的id值,SoftReference對應該圖片的軟引用

    private Bitmap mLoadBitmap;//GridView中默認的背景圖片
    //構造器
    public ImageWorker(Context context) {
        this.mResources = context.getResources();
        this.mContentResolver = context.getContentResolver();
        mOptions = new BitmapFactory.Options();
        mOptions.inSampleSize = 3;//縮放圖片為原來的1/9。一般應用中加載圖片都會進行圖片的縮放,防止內存溢出的問題。這部分的內容有關Bitmap,請參考我的博文(http://blog.csdn.net/u010156024/article/details/44103557)
    }

    /**
     * 加載圖片
     * @param origId 每個本地圖片對應一個id值
     * @param imageView
     */
    public void loadImage(long origId, ImageView imageView) {
        BitmapDrawable bitmapDrawable = null;
        //先從緩存中加載圖片,如果緩存中有,加載圖片即可。
        //如果緩存中沒有,首先判斷當前任務是否暫停,沒有暫停則使用loadBitmapTask異步任務線程加載圖片
        if (bitmapCache.containsKey(origId)) {
            bitmapDrawable = bitmapCache.get(origId).get();
        }
        if (bitmapDrawable != null) {
            imageView.setImageDrawable(bitmapDrawable);
        } else if (cancelPotentialWork(origId, imageView)) {
            final LoadBitmapTask loadBitmapTask = new LoadBitmapTask(imageView);
            final AsyncDrawable asyncDrawable =
                    new AsyncDrawable(mResources, mLoadBitmap, loadBitmapTask);
            imageView.setImageDrawable(asyncDrawable);
            //SERIAL_EXECUTOR 啟動線程,保證線程順序依次執行
            loadBitmapTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, origId);
        }
    }

/**
* 該類提供這個方法設置GridView中每個item默認的圖片
*/
    public void setLoadBitmap(Bitmap mLoadBitmap) {
        this.mLoadBitmap = mLoadBitmap;
    }

    /**
     * 設置圖片動畫  加載圖片漸隱漸顯的效果
     *
     * @param imageView
     * @param drawable
     */
    private void setImageDrawable(ImageView imageView, Drawable drawable) {
        final TransitionDrawable td =
                new TransitionDrawable(new Drawable[]{
                        new ColorDrawable(android.R.color.transparent),
                        drawable
                });
        imageView.setImageDrawable(td);
        td.startTransition(FADE_IN_TIME);
    }

    /**
     * 取消可能在運行並且暫停的任務。
     *
     * @param origId
     * @param imageView
     * @return
     */
    private static boolean cancelPotentialWork(long origId, ImageView imageView) {
        final LoadBitmapTask loadBitmapTask = getBitmapWorkerTask(imageView);

        if (loadBitmapTask != null) {
            final long bitmapOrigId = loadBitmapTask.origId;
            if (bitmapOrigId == origId) {
                loadBitmapTask.cancel(true);
            } else {
                // The same work is already in progress.
                return false;
            }
        }
        return true;
    }

    /**
     * 圖片異步加載線程類-任務線程
     */
    private class LoadBitmapTask extends AsyncTask {
        private long origId;
        private WeakReference imageViewReference;//指向Imageview的弱引用,把圖片緩存在HashMap> bitmapCache中。

        public LoadBitmapTask(ImageView imageView) {
            imageViewReference = new WeakReference(imageView);
        }

        @Override
        protected BitmapDrawable doInBackground(Long... params) {
            origId = params[0];
            Bitmap bitmap = null;
            BitmapDrawable drawable = null;

            // Wait here if work is paused and the task is not cancelled
            synchronized (mPauseWorkLock) {
                while (mPauseWork && !isCancelled()) {
                    try {
                        mPauseWorkLock.wait();
                    } catch (InterruptedException e) {
                    }
                }
            }

            if (bitmapCache != null && !isCancelled() && getAttachedImageView() != null
                    && !mExitTasksEarly) {
                //這裡是根據圖片的id值查詢手機本地的圖片,獲取圖片的縮略圖,MICRO_KIND 代表96*96大小的圖片
                bitmap = MediaStore.Images.Thumbnails.getThumbnail(
                        mContentResolver,
                        origId,
                    MediaStore.Images.Thumbnails.MICRO_KIND,
                        mOptions
                );
            }

            if (bitmap != null) {
                drawable = new BitmapDrawable(mResources, bitmap);
                bitmapCache.put(origId,new SoftReference(drawable));
            }
            return drawable;
        }

        @Override
        protected void onPostExecute(BitmapDrawable drawable) {
            if (isCancelled() || mExitTasksEarly) {
                drawable = null;
            }

            final ImageView imageView = getAttachedImageView();
            if (drawable != null && imageView != null) {
                setImageDrawable(imageView, drawable);
            }
        }

       @Override
        protected void onCancelled(BitmapDrawable drawable) {
            super.onCancelled(drawable);
            synchronized (mPauseWorkLock) {
                mPauseWorkLock.notifyAll();
            }
        }

        /**
         * 返回與此任務相關的ImageView,
         * 如果ImageView 內的任務是當前任務,
         * 則返回當前ImageView,否則返回null。
         * @return
         */
        private ImageView getAttachedImageView() {
            final ImageView imageView = imageViewReference.get();
            final LoadBitmapTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
            if (this == bitmapWorkerTask) {
                return imageView;
            }
            return null;
        }
    }

    /**
     * 存儲異步信息圖片資源類
     */
    private static class AsyncDrawable extends BitmapDrawable {
        private final WeakReference bitmapWorkerTaskReference;//虛引用
        public AsyncDrawable(Resources res, Bitmap bitmap, LoadBitmapTask bitmapWorkerTask) {
            super(res, bitmap);
            bitmapWorkerTaskReference =
                    new WeakReference(bitmapWorkerTask);
        }
        public LoadBitmapTask getLoadBitmapTask() {
            return bitmapWorkerTaskReference.get();
        }
    }

    /**
     * 返回圖片資源內存放的異步線程,如果存在,則返回,不存在,返回null。
     *
     * @param imageView 當前存放異步資源圖片的ImageView
     * @return
     */
    private static LoadBitmapTask getBitmapWorkerTask(ImageView imageView) {
        if (imageView != null) {
            final Drawable drawable = imageView.getDrawable();
            if (drawable instanceof AsyncDrawable) {
                final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
                return asyncDrawable.getLoadBitmapTask();
            }
        }
        return null;
    }

    /**
     * 設置異步任務是否暫停,false為啟動,true為暫停。
     * @param pauseWork
     */
    public void setPauseWork(boolean pauseWork) {
        synchronized (mPauseWorkLock) {
            mPauseWork = pauseWork;
            if (!mPauseWork) {
                mPauseWorkLock.notifyAll();
            }
        }
    }

    /**
     * 退出線程
     * @param exitTasksEarly
     */
    public void setExitTasksEarly(boolean exitTasksEarly) {
        mExitTasksEarly = exitTasksEarly;
        setPauseWork(false);//這個設置為false,使得退出任務優雅。這個設置為true也是可行的,也沒有問題,可以達到同樣的效果。但是可以比較設置為true或false的區別。
    }
}

至此 全部講述了android手機中獲取本地圖片的全部內容。這個項目代碼在Github中開放學習,非常值得大家深入研究學習之後。
總結:
整個項目使用到了ContentResolver、軟引用、弱引用、緩存、異步線程、節省內存技巧-滾動不加載、鎖機制、圖片縮放、線程通信、動畫等非常實用的方法、技巧。

 

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