Android Open Source - cube-sdk Image Loader






From Project

Back to project page cube-sdk.

License

The source code is released under:

Apache License

If you think the Android project cube-sdk listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package in.srain.cube.image;
/* w ww.  ja va 2  s  . com*/
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import in.srain.cube.app.CubeFragment;
import in.srain.cube.app.lifecycle.LifeCycleComponent;
import in.srain.cube.app.lifecycle.LifeCycleComponentManager;
import in.srain.cube.concurrent.SimpleTask;
import in.srain.cube.image.iface.ImageLoadHandler;
import in.srain.cube.image.iface.ImageLoadProgressHandler;
import in.srain.cube.image.iface.ImageResizer;
import in.srain.cube.image.iface.ImageTaskExecutor;
import in.srain.cube.util.CLog;
import in.srain.cube.util.Debug;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;

/**
 * @author http://www.liaohuqiu.net
 */
public class ImageLoader implements LifeCycleComponent {

    private static final String MSG_ATTACK_TO_RUNNING_TASK = "%s attach to running: %s";

    private static final String MSG_TASK_DO_IN_BACKGROUND = "%s doInBackground";
    private static final String MSG_TASK_FINISH = "%s onFinish";
    private static final String MSG_TASK_CANCEL = "%s onCancel";
    private static final String MSG_TASK_HIT_CACHE = "%s hit cache %s %s";

    protected static final boolean DEBUG = Debug.DEBUG_IMAGE;
    protected static final String LOG_TAG = Debug.DEBUG_IMAGE_LOG_TAG;

    protected ImageTaskExecutor mImageTaskExecutor;
    protected ImageResizer mImageResizer;
    protected ImageProvider mImageProvider;
    protected ImageLoadHandler mImageLoadHandler;
    protected ImageLoadProgressHandler mLoadProgressHandler;

    protected boolean mPauseWork = false;
    protected boolean mExitTasksEarly = false;

    private final Object mPauseWorkLock = new Object();
    private HashMap<String, LoadImageTask> mLoadWorkList;
    protected Context mContext;

    protected Resources mResources;

    public enum ImageTaskOrder {
        FIRST_IN_FIRST_OUT, LAST_IN_FIRST_OUT
    }

    public ImageLoader(Context context, ImageProvider imageProvider, ImageTaskExecutor imageTaskExecutor, ImageResizer imageResizer, ImageLoadHandler imageLoadHandler) {
        mContext = context;
        mResources = context.getResources();

        mImageProvider = imageProvider;
        mImageTaskExecutor = imageTaskExecutor;
        mImageResizer = imageResizer;
        mImageLoadHandler = imageLoadHandler;

        mLoadWorkList = new HashMap<String, LoadImageTask>();
    }

    public void setImageLoadHandler(ImageLoadHandler imageLoadHandler) {
        mImageLoadHandler = imageLoadHandler;
    }

    public ImageLoadHandler getImageLoadHandler() {
        return mImageLoadHandler;
    }

    public void setImageResizer(ImageResizer resizer) {
        mImageResizer = resizer;
    }

    public ImageResizer getImageResizer() {
        return mImageResizer;
    }

    public ImageProvider getImageProvider() {
        return mImageProvider;
    }

    /**
     * Load the image in advance.
     */
    public void preLoadImages(String[] urls) {
        int len = urls.length;
        for (int i = 0; i < len; i++) {
            final ImageTask imageTask = createImageTask(urls[i], 0, 0, null);
            imageTask.setIsPreLoad();
            addImageTask(imageTask, null);
        }
    }

    /**
     * Create an ImageTask.
     * <p/>
     * You can override this method to return a customized ImagetTask.
     *
     * @param url
     * @param requestWidth
     * @param requestHeight
     * @param imageReuseInfo
     * @return
     */
    public ImageTask createImageTask(String url, int requestWidth, int requestHeight, ImageReuseInfo imageReuseInfo) {
        ImageTask imageTask = ImageTask.obtain();
        if (imageTask == null) {
            imageTask = new ImageTask();
        }
        imageTask.renew().setOriginUrl(url).setRequestSize(requestWidth, requestHeight).setReuseInfo(imageReuseInfo);
        return imageTask;
    }

    /**
     * Detach the ImageView from the ImageTask.
     *
     * @param imageTask
     * @param imageView
     */
    public void detachImageViewFromImageTask(ImageTask imageTask, CubeImageView imageView) {
        imageTask.removeImageView(imageView);
        if (imageTask.isLoading()) {
            if (!imageTask.isPreLoad() && !imageTask.stillHasRelatedImageView()) {
                LoadImageTask task = mLoadWorkList.get(imageTask.getIdentityKey());
                if (task != null) {
                    task.cancel(true);
                }
                if (DEBUG) {
                    CLog.d(LOG_TAG, "%s previous work is cancelled.", imageTask);
                }
            }
        }
        if (!imageTask.stillHasRelatedImageView()) {
            imageTask.tryToRecycle();
        }
    }

    /**
     * Add the ImageTask into loading list.
     *
     * @param imageTask
     * @param imageView
     */
    public void addImageTask(ImageTask imageTask, CubeImageView imageView) {
        LoadImageTask runningTask = mLoadWorkList.get(imageTask.getIdentityKey());
        if (runningTask != null) {
            if (imageView != null) {
                if (DEBUG) {
                    CLog.d(LOG_TAG, MSG_ATTACK_TO_RUNNING_TASK, imageTask, runningTask.getImageTask());
                }
                runningTask.getImageTask().addImageView(imageView);
            }
            return;
        } else {
            imageTask.addImageView(imageView);
        }

        imageTask.onLoading(mImageLoadHandler);

        LoadImageTask loadImageTask = new LoadImageTask(imageTask);
        mLoadWorkList.put(imageTask.getIdentityKey(), loadImageTask);
        mImageTaskExecutor.execute(loadImageTask);
    }

    /**
     * Check weather this imageTask has cache Drawable data.
     */
    public boolean queryCache(ImageTask imageTask, CubeImageView imageView) {
        if (null == mImageProvider) {
            return false;
        }
        BitmapDrawable drawable = mImageProvider.getBitmapFromMemCache(imageTask);

        if (imageTask.getStatistics() != null) {
            imageTask.getStatistics().afterMemoryCache(drawable != null);
        }
        if (drawable == null) {
            return false;
        }

        if (DEBUG) {
            CLog.d(LOG_TAG, MSG_TASK_HIT_CACHE, imageTask, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
            if (drawable.getIntrinsicWidth() == 270) {
                CLog.d(LOG_TAG, MSG_TASK_HIT_CACHE, imageTask, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
            }
        }
        imageTask.addImageView(imageView);
        imageTask.onLoadFinish(drawable, mImageLoadHandler);
        return true;
    }

    public void setTaskOrder(ImageTaskOrder order) {
        if (null != mImageTaskExecutor) {
            mImageTaskExecutor.setTaskOrder(order);
        }
    }

    /**
     * flush un-cached image to disk
     */
    public void flushFileCache() {
        if (mImageProvider != null) {
            mImageProvider.flushFileCache();
        }
    }

    /**
     * Inner class to process the image loading task in background threads.
     *
     * @author http://www.liaohuqiu.net
     */
    private class LoadImageTask extends SimpleTask {

        private ImageTask mImageTask;
        private BitmapDrawable mDrawable;

        public LoadImageTask(ImageTask imageTask) {
            this.mImageTask = imageTask;
        }

        public ImageTask getImageTask() {
            return mImageTask;
        }

        @Override
        public void doInBackground() {
            if (DEBUG) {
                CLog.d(LOG_TAG, MSG_TASK_DO_IN_BACKGROUND, mImageTask);
            }

            if (mImageTask.getStatistics() != null) {
                mImageTask.getStatistics().beginLoad();
            }
            Bitmap bitmap = null;
            // Wait here if work is paused and the task is not cancelled
            synchronized (mPauseWorkLock) {
                while (mPauseWork && !isCancelled()) {
                    try {
                        if (DEBUG) {
                            CLog.d(LOG_TAG, "%s wait to begin", mImageTask);
                        }
                        mPauseWorkLock.wait();
                    } catch (InterruptedException e) {
                    }
                }
            }

            // If this task has not been cancelled by another
            // thread and the ImageView that was originally bound to this task is still bound back
            // to this task and our "exit early" flag is not set then try and fetch the bitmap from
            // the cache
            if (!isCancelled() && !mExitTasksEarly && (mImageTask.isPreLoad() || mImageTask.stillHasRelatedImageView())) {
                try {
                    bitmap = mImageProvider.fetchBitmapData(ImageLoader.this, mImageTask, mImageResizer);
                    if (mImageTask.getStatistics() != null) {
                        mImageTask.getStatistics().afterDecode();
                    }
                    mDrawable = mImageProvider.createBitmapDrawable(mResources, bitmap);
                    mImageProvider.addBitmapToMemCache(mImageTask.getIdentityKey(), mDrawable);
                    if (mImageTask.getStatistics() != null) {
                        mImageTask.getStatistics().afterCreateBitmapDrawable();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } catch (OutOfMemoryError e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void onFinish() {
            if (DEBUG) {
                CLog.d(LOG_TAG, MSG_TASK_FINISH, mImageTask);
            }
            if (mExitTasksEarly) {
                return;
            }
            mLoadWorkList.remove(mImageTask.getIdentityKey());

            if (!isCancelled() && !mExitTasksEarly) {
                mImageTask.onLoadFinish(mDrawable, mImageLoadHandler);
            }
            mImageTask.tryToRecycle();
        }

        @Override
        public void onCancel() {
            if (DEBUG) {
                CLog.d(LOG_TAG, MSG_TASK_CANCEL, mImageTask);
            }
            mLoadWorkList.remove(mImageTask.getIdentityKey());
            mImageTask.onCancel();
            mImageTask.tryToRecycle();
        }
    }

    private void setPause(boolean pause) {
        synchronized (mPauseWorkLock) {
            mPauseWork = pause;
            if (!pause) {
                mPauseWorkLock.notifyAll();
            }
        }
    }

    /**
     * Temporarily hand up work, you can call this when the view is scrolling.
     */
    public void pauseWork() {
        mExitTasksEarly = false;
        setPause(true);
        if (DEBUG) {
            CLog.d(LOG_TAG, "work_status: pauseWork %s", this);
        }
    }

    /**
     * Resume the work
     */
    public void resumeWork() {
        mExitTasksEarly = false;
        setPause(false);
        if (DEBUG) {
            CLog.d(LOG_TAG, "work_status: resumeWork %s", this);
        }
    }

    /**
     * Recover the from the work list
     */
    public void recoverWork() {
        if (DEBUG) {
            CLog.d(LOG_TAG, "work_status: recoverWork %s", this);
        }
        mExitTasksEarly = false;
        setPause(false);
        Iterator<Entry<String, LoadImageTask>> it = (Iterator<Entry<String, LoadImageTask>>) mLoadWorkList.entrySet().iterator();
        while (it.hasNext()) {
            Entry<String, LoadImageTask> item = it.next();
            LoadImageTask task = item.getValue();
            task.restart();
            mImageTaskExecutor.execute(task);
        }
    }

    /**
     * Drop all the work, and leave it in the work list.
     */
    public void stopWork() {
        if (DEBUG) {
            CLog.d(LOG_TAG, "work_status: stopWork %s", this);
        }
        mExitTasksEarly = true;
        setPause(false);

        flushFileCache();
    }

    /**
     * Drop all the work, clear the work list.
     */
    public void destroy() {
        if (DEBUG) {
            CLog.d(LOG_TAG, "work_status: destroy %s", this);
        }
        mExitTasksEarly = true;
        setPause(false);

        Iterator<Entry<String, LoadImageTask>> it = (Iterator<Entry<String, LoadImageTask>>) mLoadWorkList.entrySet().iterator();
        while (it.hasNext()) {
            Entry<String, LoadImageTask> item = it.next();
            final LoadImageTask task = item.getValue();
            it.remove();
            if (task != null) {
                task.cancel(true);
            }
        }
        mLoadWorkList.clear();
    }

    /**
     * The UI becomes partially invisible.
     * like {@link android.app.Activity#onPause}
     */
    @Override
    public void onBecomesPartiallyInvisible() {
        pauseWork();
    }

    /**
     * The UI becomes visible from partially invisible.
     * like {@link android.app.Activity#onResume}
     */
    @Override
    public void onBecomesVisible() {
        resumeWork();
    }

    /**
     * The UI becomes totally invisible.
     * like {@link android.app.Activity#onStop}
     */
    @Override
    public void onBecomesTotallyInvisible() {
        stopWork();
    }

    /**
     * The UI becomes visible from totally invisible.
     * like {@link android.app.Activity#onRestart}
     */
    @Override
    public void onBecomesVisibleFromTotallyInvisible() {
        recoverWork();
    }

    /**
     * like {@link android.app.Activity#onDestroy}
     */
    @Override
    public void onDestroy() {
        destroy();
    }

    /**
     * try to attach to {@link in.srain.cube.app.lifecycle.IComponentContainer}
     */
    public ImageLoader tryToAttachToContainer(Object object) {
        tryToAttachToContainer(object, true);
        return this;
    }

    /**
     * try to attach to {@link in.srain.cube.app.lifecycle.IComponentContainer}
     */
    public ImageLoader tryToAttachToContainer(Object object, boolean throwEx) {
        LifeCycleComponentManager.tryAddComponentToContainer(this, object, throwEx);
        return this;
    }

    /**
     * Process LifeCycle
     *
     * @param fragment
     * @return
     */
    public ImageLoader attachToCubeFragment(CubeFragment fragment) {
        if (fragment != null) {
            LifeCycleComponentManager.tryAddComponentToContainer(this, fragment);
        }
        return this;
    }
}




Java Source Code List

in.srain.cube.Cube.java
in.srain.cube.app.CubeFragmentActivity.java
in.srain.cube.app.CubeFragment.java
in.srain.cube.app.FragmentParam.java
in.srain.cube.app.ICubeFragment.java
in.srain.cube.app.XActivity.java
in.srain.cube.app.lifecycle.IComponentContainer.java
in.srain.cube.app.lifecycle.LifeCycleComponentManager.java
in.srain.cube.app.lifecycle.LifeCycleComponent.java
in.srain.cube.cache.CacheInfo.java
in.srain.cube.cache.CacheManager.java
in.srain.cube.cache.CacheResultType.java
in.srain.cube.cache.ICacheAble.java
in.srain.cube.cache.IFileCache.java
in.srain.cube.cache.QueryHandler.java
in.srain.cube.cache.Query.java
in.srain.cube.concurrent.BlockingDeque.java
in.srain.cube.concurrent.Deque.java
in.srain.cube.concurrent.LinkedBlockingDeque.java
in.srain.cube.concurrent.SimpleExecutor.java
in.srain.cube.concurrent.SimpleTask.java
in.srain.cube.file.DiskLruCache.java
in.srain.cube.file.FileUtil.java
in.srain.cube.file.LruFileCache.java
in.srain.cube.image.CubeImageView.java
in.srain.cube.image.ImageLoaderFactory.java
in.srain.cube.image.ImageLoader.java
in.srain.cube.image.ImagePerformanceStatistics.java
in.srain.cube.image.ImageProvider.java
in.srain.cube.image.ImageReuseInfoManger.java
in.srain.cube.image.ImageReuseInfo.java
in.srain.cube.image.ImageTaskStatistics.java
in.srain.cube.image.ImageTask.java
in.srain.cube.image.drawable.RecyclingBitmapDrawable.java
in.srain.cube.image.drawable.RoundedDrawable.java
in.srain.cube.image.iface.ImageFileProvider.java
in.srain.cube.image.iface.ImageLoadHandler.java
in.srain.cube.image.iface.ImageLoadProgressHandler.java
in.srain.cube.image.iface.ImageMemoryCache.java
in.srain.cube.image.iface.ImageResizer.java
in.srain.cube.image.iface.ImageTaskExecutor.java
in.srain.cube.image.impl.DefaultImageLoadHandler.java
in.srain.cube.image.impl.DefaultImageResizer.java
in.srain.cube.image.impl.DefaultImageTaskExecutor.java
in.srain.cube.image.impl.DefaultMemoryCache.java
in.srain.cube.image.impl.LruImageFileProvider.java
in.srain.cube.image.impl.SimpleDownloader.java
in.srain.cube.mints.base.BlockMenuFragment.java
in.srain.cube.mints.base.DemoBaseActivity.java
in.srain.cube.mints.base.TitleBaseActivity.java
in.srain.cube.mints.base.TitleBaseFragment.java
in.srain.cube.mints.base.TitleHeaderBar.java
in.srain.cube.request.CacheAbleRequestDefaultHandler.java
in.srain.cube.request.CacheAbleRequestHandler.java
in.srain.cube.request.CacheAbleRequestJsonHandler.java
in.srain.cube.request.CacheAbleRequest.java
in.srain.cube.request.FailData.java
in.srain.cube.request.ICacheAbleRequest.java
in.srain.cube.request.IRequest.java
in.srain.cube.request.JsonData.java
in.srain.cube.request.RequestBase.java
in.srain.cube.request.RequestCacheManager.java
in.srain.cube.request.RequestData.java
in.srain.cube.request.RequestDefaultHandler.java
in.srain.cube.request.RequestFinishHandler.java
in.srain.cube.request.RequestHandler.java
in.srain.cube.request.RequestJsonHandler.java
in.srain.cube.request.SimpleJsonRequest.java
in.srain.cube.request.SimpleRequestManager.java
in.srain.cube.request.SimpleRequest.java
in.srain.cube.uri.CustomizedUri.java
in.srain.cube.util.Debug.java
in.srain.cube.util.Encrypt.java
in.srain.cube.util.Env.java
in.srain.cube.util.LocalDisplay.java
in.srain.cube.util.NetworkStatusManager.java
in.srain.cube.util.ResourceMan.java
in.srain.cube.util.SystemWatcher.java
in.srain.cube.util.Version.java
in.srain.cube.views.DotView.java
in.srain.cube.views.IScrollHeaderFrameHandler.java
in.srain.cube.views.MoreActionView.java
in.srain.cube.views.ScrollHeaderFrame.java
in.srain.cube.views.banner.BannerAdapter.java
in.srain.cube.views.banner.PagerIndicator.java
in.srain.cube.views.banner.SliderBanner.java
in.srain.cube.views.block.BlockListAdapter.java
in.srain.cube.views.block.BlockListView.java
in.srain.cube.views.list.ListPageInfo.java
in.srain.cube.views.list.ListViewDataAdapterBase.java
in.srain.cube.views.list.ListViewDataAdapter.java
in.srain.cube.views.list.PagedListDataModel.java
in.srain.cube.views.list.PagedListViewDataAdapter.java
in.srain.cube.views.list.ViewHolderBase.java
in.srain.cube.views.list.ViewHolderCreator.java
in.srain.cube.views.mix.AutoPlayer.java
in.srain.cube.views.pager.PageIndicator.java
in.srain.cube.views.pager.TabPageIndicator.java