ImageLoader.java

/*
 * Decompiled with CFR 0_132.
 * 
 * Could not load the following classes:
 *  android.annotation.SuppressLint
 *  android.app.ActivityManager
 *  android.content.Context
 *  android.graphics.Bitmap
 *  android.graphics.Paint
 *  android.graphics.drawable.BitmapDrawable
 *  android.graphics.drawable.Drawable
 *  android.text.TextUtils
 *  android.view.animation.Animation
 *  android.widget.ImageView
 *  android.widget.ImageView$ScaleType
 */
package org.xutils.image;

import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.view.animation.Animation;
import android.widget.ImageView;
import java.io.File;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicLong;
import org.xutils.cache.LruCache;
import org.xutils.cache.LruDiskCache;
import org.xutils.common.Callback;
import org.xutils.common.task.Priority;
import org.xutils.common.task.PriorityExecutor;
import org.xutils.common.util.IOUtil;
import org.xutils.common.util.LogUtil;
import org.xutils.ex.FileLockedException;
import org.xutils.http.RequestParams;
import org.xutils.image.AsyncDrawable;
import org.xutils.image.GifDrawable;
import org.xutils.image.ImageAnimationHelper;
import org.xutils.image.ImageDecoder;
import org.xutils.image.ImageOptions;
import org.xutils.image.MemCacheKey;
import org.xutils.image.ReusableDrawable;
import org.xutils.x;

final class ImageLoader
implements Callback.PrepareCallback<File, Drawable>,
Callback.CacheCallback<Drawable>,
Callback.ProgressCallback<Drawable>,
Callback.TypedCallback<Drawable>,
Callback.Cancelable {
    private MemCacheKey key;
    private ImageOptions options;
    private WeakReference<ImageView> viewRef;
    private static final AtomicLong SEQ_SEEK = new AtomicLong(0L);
    private final long seq = SEQ_SEEK.incrementAndGet();
    private volatile boolean stopped = false;
    private volatile boolean cancelled = false;
    private Callback.Cancelable cancelable;
    private Callback.CommonCallback<Drawable> callback;
    private Callback.PrepareCallback<File, Drawable> prepareCallback;
    private Callback.CacheCallback<Drawable> cacheCallback;
    private Callback.ProgressCallback<Drawable> progressCallback;
    private static final String DISK_CACHE_DIR_NAME = "xUtils_img";
    private static final Executor EXECUTOR = new PriorityExecutor(10, false);
    private static final int MEM_CACHE_MIN_SIZE = 4194304;
    private static final LruCache<MemCacheKey, Drawable> MEM_CACHE = new LruCache<MemCacheKey, Drawable>(4194304){
        private boolean deepClear = false;

        @Override
        protected int sizeOf(MemCacheKey key, Drawable value) {
            if (value instanceof BitmapDrawable) {
                Bitmap bitmap = ((BitmapDrawable)value).getBitmap();
                return bitmap == null ? 0 : bitmap.getByteCount();
            }
            if (value instanceof GifDrawable) {
                return ((GifDrawable)value).getByteCount();
            }
            return super.sizeOf(key, value);
        }

        @Override
        public void trimToSize(int maxSize) {
            if (maxSize < 0) {
                this.deepClear = true;
            }
            super.trimToSize(maxSize);
            this.deepClear = false;
        }

        @Override
        protected void entryRemoved(boolean evicted, MemCacheKey key, Drawable oldValue, Drawable newValue) {
            super.entryRemoved(evicted, key, oldValue, newValue);
            if (evicted && this.deepClear && oldValue instanceof ReusableDrawable) {
                ((ReusableDrawable)oldValue).setMemCacheKey(null);
            }
        }
    };
    private static final HashMap<String, FakeImageView> FAKE_IMG_MAP;
    private static final Type loadType;
    private boolean hasCache = false;

    private ImageLoader() {
    }

    static void clearMemCache() {
        MEM_CACHE.evictAll();
    }

    static void clearCacheFiles() {
        LruDiskCache.getDiskCache(DISK_CACHE_DIR_NAME).clearCacheFiles();
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    static Callback.Cancelable doLoadDrawable(String url, ImageOptions options, Callback.CommonCallback<Drawable> callback) {
        if (TextUtils.isEmpty((CharSequence)url)) {
            ImageLoader.postArgsException(null, options, "url is null", callback);
            return null;
        }
        FakeImageView fakeImageView = null;
        HashMap<String, FakeImageView> hashMap = FAKE_IMG_MAP;
        synchronized (hashMap) {
            fakeImageView = FAKE_IMG_MAP.get(url);
            if (fakeImageView == null) {
                fakeImageView = new FakeImageView();
            }
        }
        return ImageLoader.doBind(fakeImageView, url, options, callback);
    }

    static Callback.Cancelable doLoadFile(String url, ImageOptions options, Callback.CacheCallback<File> callback) {
        if (TextUtils.isEmpty((CharSequence)url)) {
            ImageLoader.postArgsException(null, options, "url is null", callback);
            return null;
        }
        RequestParams params = ImageLoader.createRequestParams(url, options);
        return x.http().get(params, callback);
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     * Enabled force condition propagation
     * Lifted jumps to return sites
     */
    static Callback.Cancelable doBind(ImageView view, String url, ImageOptions options, Callback.CommonCallback<Drawable> callback) {
        Bitmap bitmap;
        MemCacheKey oldKey;
        ImageOptions localOptions = options;
        if (view == null) {
            ImageLoader.postArgsException(null, localOptions, "view is null", callback);
            return null;
        }
        if (TextUtils.isEmpty((CharSequence)url)) {
            ImageLoader.postArgsException(view, localOptions, "url is null", callback);
            return null;
        }
        if (localOptions == null) {
            localOptions = ImageOptions.DEFAULT;
        }
        localOptions.optimizeMaxSize(view);
        MemCacheKey key = new MemCacheKey(url, localOptions);
        Drawable oldDrawable = view.getDrawable();
        if (oldDrawable instanceof AsyncDrawable) {
            ImageLoader loader = ((AsyncDrawable)oldDrawable).getImageLoader();
            if (loader != null && !loader.stopped) {
                if (key.equals(loader.key)) {
                    return null;
                }
                loader.cancel();
            }
        } else if (oldDrawable instanceof ReusableDrawable && (oldKey = ((ReusableDrawable)oldDrawable).getMemCacheKey()) != null && oldKey.equals(key)) {
            MEM_CACHE.put(key, oldDrawable);
        }
        Drawable memDrawable = null;
        if (!localOptions.isUseMemCache()) return new ImageLoader().doLoad(view, url, localOptions, callback);
        memDrawable = MEM_CACHE.get(key);
        if (memDrawable instanceof BitmapDrawable && ((bitmap = ((BitmapDrawable)memDrawable).getBitmap()) == null || bitmap.isRecycled())) {
            return new ImageLoader().doLoad(view, url, localOptions, callback);
        }
        if (memDrawable == null) return new ImageLoader().doLoad(view, url, localOptions, callback);
        boolean trustMemCache = false;
        try {
            if (callback instanceof Callback.ProgressCallback) {
                ((Callback.ProgressCallback)callback).onWaiting();
            }
            view.setScaleType(localOptions.getImageScaleType());
            view.setImageDrawable(memDrawable);
            trustMemCache = true;
            if (callback instanceof Callback.CacheCallback) {
                trustMemCache = ((Callback.CacheCallback)callback).onCache(memDrawable);
                if (trustMemCache) return null;
                Callback.Cancelable cancelable = new ImageLoader().doLoad(view, url, localOptions, callback);
                return cancelable;
            }
            if (callback == null) return null;
            callback.onSuccess(memDrawable);
            return null;
        }
        catch (Throwable ex) {
            LogUtil.e(ex.getMessage(), ex);
            trustMemCache = false;
            Callback.Cancelable ignored = new ImageLoader().doLoad(view, url, localOptions, callback);
            return ignored;
        }
        finally {
            if (trustMemCache && callback != null) {
                try {
                    callback.onFinished();
                }
                catch (Throwable ignored) {
                    LogUtil.e(ignored.getMessage(), ignored);
                }
            }
        }
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    private Callback.Cancelable doLoad(ImageView view, String url, ImageOptions options, Callback.CommonCallback<Drawable> callback) {
        this.viewRef = new WeakReference<ImageView>(view);
        this.options = options;
        this.key = new MemCacheKey(url, options);
        this.callback = callback;
        if (callback instanceof Callback.ProgressCallback) {
            this.progressCallback = (Callback.ProgressCallback)callback;
        }
        if (callback instanceof Callback.PrepareCallback) {
            this.prepareCallback = (Callback.PrepareCallback)callback;
        }
        if (callback instanceof Callback.CacheCallback) {
            this.cacheCallback = (Callback.CacheCallback)callback;
        }
        Drawable loadingDrawable = null;
        if (options.isForceLoadingDrawable()) {
            loadingDrawable = options.getLoadingDrawable(view);
            view.setScaleType(options.getPlaceholderScaleType());
            view.setImageDrawable((Drawable)new AsyncDrawable(this, loadingDrawable));
        } else {
            loadingDrawable = view.getDrawable();
            view.setImageDrawable((Drawable)new AsyncDrawable(this, loadingDrawable));
        }
        RequestParams params = ImageLoader.createRequestParams(url, options);
        if (view instanceof FakeImageView) {
            HashMap<String, FakeImageView> hashMap = FAKE_IMG_MAP;
            synchronized (hashMap) {
                FAKE_IMG_MAP.put(url, (FakeImageView)view);
            }
        }
        this.cancelable = x.http().get(params, this);
        return this.cancelable;
    }

    @Override
    public void cancel() {
        this.stopped = true;
        this.cancelled = true;
        if (this.cancelable != null) {
            this.cancelable.cancel();
        }
    }

    @Override
    public boolean isCancelled() {
        return this.cancelled || !this.validView4Callback(false);
    }

    @Override
    public void onWaiting() {
        if (this.progressCallback != null) {
            this.progressCallback.onWaiting();
        }
    }

    @Override
    public void onStarted() {
        if (this.validView4Callback(true) && this.progressCallback != null) {
            this.progressCallback.onStarted();
        }
    }

    @Override
    public void onLoading(long total, long current, boolean isDownloading) {
        if (this.validView4Callback(true) && this.progressCallback != null) {
            this.progressCallback.onLoading(total, current, isDownloading);
        }
    }

    @Override
    public Type getLoadType() {
        return loadType;
    }

    @Override
    public Drawable prepare(File rawData) {
        if (!this.validView4Callback(true)) {
            return null;
        }
        try {
            Drawable result = null;
            if (this.prepareCallback != null) {
                result = this.prepareCallback.prepare(rawData);
            }
            if (result == null) {
                result = ImageDecoder.decodeFileWithLock(rawData, this.options, this);
            }
            if (result != null && result instanceof ReusableDrawable) {
                ((ReusableDrawable)result).setMemCacheKey(this.key);
                MEM_CACHE.put(this.key, result);
            }
            return result;
        }
        catch (IOException ex) {
            IOUtil.deleteFileOrDir(rawData);
            LogUtil.w(ex.getMessage(), ex);
            return null;
        }
    }

    @Override
    public boolean onCache(Drawable result) {
        if (!this.validView4Callback(true)) {
            return false;
        }
        if (result != null) {
            this.hasCache = true;
            this.setSuccessDrawable4Callback(result);
            if (this.cacheCallback != null) {
                return this.cacheCallback.onCache(result);
            }
            if (this.callback != null) {
                this.callback.onSuccess(result);
                return true;
            }
            return true;
        }
        return false;
    }

    @Override
    public void onSuccess(Drawable result) {
        if (!this.validView4Callback(!this.hasCache)) {
            return;
        }
        if (result != null) {
            this.setSuccessDrawable4Callback(result);
            if (this.callback != null) {
                this.callback.onSuccess(result);
            }
        }
    }

    @Override
    public void onError(Throwable ex, boolean isOnCallback) {
        this.stopped = true;
        if (!this.validView4Callback(false)) {
            return;
        }
        if (ex instanceof FileLockedException) {
            LogUtil.d("ImageFileLocked: " + this.key.url);
            x.task().postDelayed(new Runnable(){

                @Override
                public void run() {
                    ImageLoader.doBind((ImageView)ImageLoader.this.viewRef.get(), ImageLoader.access$100((ImageLoader)ImageLoader.this).url, ImageLoader.this.options, ImageLoader.this.callback);
                }
            }, 10L);
            return;
        }
        LogUtil.e(this.key.url, ex);
        this.setErrorDrawable4Callback();
        if (this.callback != null) {
            this.callback.onError(ex, isOnCallback);
        }
    }

    @Override
    public void onCancelled(Callback.CancelledException cex) {
        this.stopped = true;
        if (!this.validView4Callback(false)) {
            return;
        }
        if (this.callback != null) {
            this.callback.onCancelled(cex);
        }
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    @Override
    public void onFinished() {
        this.stopped = true;
        ImageView view = this.viewRef.get();
        if (view instanceof FakeImageView) {
            HashMap<String, FakeImageView> hashMap = FAKE_IMG_MAP;
            synchronized (hashMap) {
                FAKE_IMG_MAP.remove(this.key.url);
            }
        }
        if (!this.validView4Callback(false)) {
            return;
        }
        if (this.callback != null) {
            this.callback.onFinished();
        }
    }

    private static RequestParams createRequestParams(String url, ImageOptions options) {
        ImageOptions.ParamsBuilder paramsBuilder;
        RequestParams params = new RequestParams(url);
        params.setCacheDirName(DISK_CACHE_DIR_NAME);
        params.setConnectTimeout(8000);
        params.setPriority(Priority.BG_LOW);
        params.setExecutor(EXECUTOR);
        params.setCancelFast(true);
        params.setUseCookie(false);
        if (options != null && (paramsBuilder = options.getParamsBuilder()) != null) {
            params = paramsBuilder.buildParams(params, options);
        }
        return params;
    }

    private boolean validView4Callback(boolean forceValidAsyncDrawable) {
        ImageView view = this.viewRef.get();
        if (view != null) {
            Drawable otherDrawable = view.getDrawable();
            if (otherDrawable instanceof AsyncDrawable) {
                ImageLoader otherLoader = ((AsyncDrawable)otherDrawable).getImageLoader();
                if (otherLoader != null) {
                    if (otherLoader == this) {
                        if (view.getVisibility() != 0) {
                            otherLoader.cancel();
                            return false;
                        }
                        return true;
                    }
                    if (this.seq > otherLoader.seq) {
                        otherLoader.cancel();
                        return true;
                    }
                    this.cancel();
                    return false;
                }
            } else if (forceValidAsyncDrawable) {
                this.cancel();
                return false;
            }
            return true;
        }
        return false;
    }

    private void setSuccessDrawable4Callback(Drawable drawable) {
        ImageView view = this.viewRef.get();
        if (view != null) {
            view.setScaleType(this.options.getImageScaleType());
            if (drawable instanceof GifDrawable) {
                if (view.getScaleType() == ImageView.ScaleType.CENTER) {
                    view.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
                }
                view.setLayerType(1, null);
            }
            if (this.options.getAnimation() != null) {
                ImageAnimationHelper.animationDisplay(view, drawable, this.options.getAnimation());
            } else if (this.options.isFadeIn()) {
                ImageAnimationHelper.fadeInDisplay(view, drawable);
            } else {
                view.setImageDrawable(drawable);
            }
        }
    }

    private void setErrorDrawable4Callback() {
        ImageView view = this.viewRef.get();
        if (view != null) {
            Drawable drawable = this.options.getFailureDrawable(view);
            view.setScaleType(this.options.getPlaceholderScaleType());
            view.setImageDrawable(drawable);
        }
    }

    private static void postArgsException(final ImageView view, final ImageOptions options, final String exMsg, final Callback.CommonCallback<?> callback) {
        x.task().autoPost(new Runnable(){

            @Override
            public void run() {
                try {
                    if (callback instanceof Callback.ProgressCallback) {
                        ((Callback.ProgressCallback)callback).onWaiting();
                    }
                    if (view != null && options != null) {
                        view.setScaleType(options.getPlaceholderScaleType());
                        view.setImageDrawable(options.getFailureDrawable(view));
                    }
                    if (callback != null) {
                        callback.onError(new IllegalArgumentException(exMsg), false);
                    }
                }
                catch (Throwable ex) {
                    if (callback != null) {
                        try {
                            callback.onError(ex, true);
                        }
                        catch (Throwable ignored) {
                            LogUtil.e(ignored.getMessage(), ignored);
                        }
                    }
                }
                finally {
                    if (callback != null) {
                        try {
                            callback.onFinished();
                        }
                        catch (Throwable ignored) {
                            LogUtil.e(ignored.getMessage(), ignored);
                        }
                    }
                }
            }
        });
    }

    static /* synthetic */ MemCacheKey access$100(ImageLoader x0) {
        return x0.key;
    }

    static {
        int memClass = ((ActivityManager)x.app().getSystemService("activity")).getMemoryClass();
        int cacheSize = 1048576 * memClass / 8;
        if (cacheSize < 4194304) {
            cacheSize = 4194304;
        }
        MEM_CACHE.resize(cacheSize);
        FAKE_IMG_MAP = new HashMap();
        loadType = File.class;
    }

    @SuppressLint(value={"ViewConstructor"})
    private static final class FakeImageView
    extends ImageView {
        private Drawable drawable;

        public FakeImageView() {
            super((Context)x.app());
        }

        public void setImageDrawable(Drawable drawable) {
            this.drawable = drawable;
        }

        public Drawable getDrawable() {
            return this.drawable;
        }

        public void setLayerType(int layerType, Paint paint) {
        }

        public void setScaleType(ImageView.ScaleType scaleType) {
        }

        public void startAnimation(Animation animation) {
        }
    }

}