Android Open Source - ion Ion






From Project

Back to project page ion.

License

The source code is released under:

Apache License

If you think the Android project ion 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 com.koushikdutta.ion;
/*ww  w  .java2s. c om*/
import android.annotation.TargetApi;
import android.app.Fragment;
import android.content.Context;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;
import android.widget.ImageView;

import com.google.gson.Gson;
import com.koushikdutta.async.AsyncServer;
import com.koushikdutta.async.future.Future;
import com.koushikdutta.async.future.FutureCallback;
import com.koushikdutta.async.http.AsyncHttpClient;
import com.koushikdutta.async.http.AsyncHttpRequest;
import com.koushikdutta.async.http.Headers;
import com.koushikdutta.async.http.cache.ResponseCacheMiddleware;
import com.koushikdutta.async.util.FileCache;
import com.koushikdutta.async.util.FileUtility;
import com.koushikdutta.async.util.HashList;
import com.koushikdutta.ion.bitmap.BitmapInfo;
import com.koushikdutta.ion.bitmap.IonBitmapCache;
import com.koushikdutta.ion.builder.Builders;
import com.koushikdutta.ion.builder.LoadBuilder;
import com.koushikdutta.ion.conscrypt.ConscryptMiddleware;
import com.koushikdutta.ion.cookie.CookieMiddleware;
import com.koushikdutta.ion.loader.AssetLoader;
import com.koushikdutta.ion.loader.AsyncHttpRequestFactory;
import com.koushikdutta.ion.loader.ContentLoader;
import com.koushikdutta.ion.loader.FileLoader;
import com.koushikdutta.ion.loader.HttpLoader;
import com.koushikdutta.ion.loader.PackageIconLoader;
import com.koushikdutta.ion.loader.ResourceLoader;
import com.koushikdutta.ion.loader.VideoLoader;

import org.apache.http.conn.ssl.BrowserCompatHostnameVerifier;

import java.io.File;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.WeakHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.net.ssl.SSLContext;

/**
 * Created by koush on 5/21/13.
 */
public class Ion {
    static final Handler mainHandler = new Handler(Looper.getMainLooper());
    static int availableProcessors = Runtime.getRuntime().availableProcessors();
    static ExecutorService ioExecutorService = Executors.newFixedThreadPool(4);
    static ExecutorService bitmapExecutorService  = availableProcessors > 2 ? Executors.newFixedThreadPool(availableProcessors - 1) : Executors.newFixedThreadPool(1);
    static HashMap<String, Ion> instances = new HashMap<String, Ion>();

    /**
     * Get the default Ion object instance and begin building a request
     * @param context
     * @return
     */
    public static LoadBuilder<Builders.Any.B> with(Context context) {
        return getDefault(context).build(context);
    }

    /**
     * the default Ion object instance and begin building a request
     * @param fragment
     * @return
     */
    @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
    public static LoadBuilder<Builders.Any.B> with(Fragment fragment) {
        return getDefault(fragment.getActivity()).build(fragment);
    }

    /**
     * the default Ion object instance and begin building a request
     * @param fragment
     * @return
     */
    public static LoadBuilder<Builders.Any.B> with(android.support.v4.app.Fragment fragment) {
        return getDefault(fragment.getActivity()).build(fragment);
    }

    /**
     * Get the default Ion instance
     * @param context
     * @return
     */
    public static Ion getDefault(Context context) {
        return getInstance(context, "ion");
    }

    /**
     * Get the given Ion instance by name
     * @param context
     * @param name
     * @return
     */
    public static Ion getInstance(Context context, String name) {
        if (context == null)
            throw new NullPointerException("Can not pass null context in to retrieve ion instance");
        Ion instance = instances.get(name);
        if (instance == null)
            instances.put(name, instance = new Ion(context, name));
        return instance;
    }

    /**
     * Create a ImageView bitmap request builder
     * @param imageView
     * @return
     */
    public static Builders.IV.F<? extends Builders.IV.F<?>> with(ImageView imageView) {
        return getDefault(imageView.getContext()).build(imageView);
    }

    AsyncHttpClient httpClient;
    ConscryptMiddleware conscryptMiddleware;
    CookieMiddleware cookieMiddleware;
    ResponseCacheMiddleware responseCache;
    FileCache storeCache;
    HttpLoader httpLoader;
    ContentLoader contentLoader;
    ResourceLoader resourceLoader;
    AssetLoader assetLoader;
    VideoLoader videoLoader;
    PackageIconLoader packageIconLoader;
    FileLoader fileLoader;
    String logtag;
    int logLevel;
    Gson gson;
    String userAgent;
    ArrayList<Loader> loaders = new ArrayList<Loader>();
    String name;
    HashList<FutureCallback<BitmapInfo>> bitmapsPending = new HashList<FutureCallback<BitmapInfo>>();
    Config config = new Config();
    IonBitmapCache bitmapCache;
    Context context;
    IonImageViewRequestBuilder bitmapBuilder = new IonImageViewRequestBuilder(this);

    private Ion(Context context, String name) {
        this.context = context = context.getApplicationContext();
        this.name = name;

        httpClient = new AsyncHttpClient(new AsyncServer("ion-" + name));
        httpClient.getSSLSocketMiddleware().setHostnameVerifier(new BrowserCompatHostnameVerifier());
        httpClient.getSSLSocketMiddleware().setSpdyEnabled(true);
        httpClient.insertMiddleware(conscryptMiddleware = new ConscryptMiddleware(context, httpClient.getSSLSocketMiddleware()));

        File ionCacheDir = new File(context.getCacheDir(), name);
        try {
            responseCache = ResponseCacheMiddleware.addCache(httpClient, ionCacheDir, 10L * 1024L * 1024L);
        }
        catch (IOException e) {
            IonLog.w("unable to set up response cache, clearing", e);
            FileUtility.deleteDirectory(ionCacheDir);
            try {
                responseCache = ResponseCacheMiddleware.addCache(httpClient, ionCacheDir, 10L * 1024L * 1024L);
            }
            catch (IOException ex) {
                IonLog.w("unable to set up response cache, failing", e);
            }
        }

        storeCache = new FileCache(new File(context.getFilesDir(), name), Long.MAX_VALUE, false);

        // TODO: Support pre GB?
        if (Build.VERSION.SDK_INT >= 9)
            addCookieMiddleware();

        httpClient.getSocketMiddleware().setConnectAllAddresses(true);
        httpClient.getSSLSocketMiddleware().setConnectAllAddresses(true);

        bitmapCache = new IonBitmapCache(this);

        configure()
                .addLoader(videoLoader = new VideoLoader())
                .addLoader(packageIconLoader = new PackageIconLoader())
                .addLoader(httpLoader = new HttpLoader())
                .addLoader(contentLoader = new ContentLoader())
                .addLoader(resourceLoader = new ResourceLoader())
                .addLoader(assetLoader = new AssetLoader())
                .addLoader(fileLoader = new FileLoader());
    }

    public static ExecutorService getBitmapLoadExecutorService() {
        return bitmapExecutorService;
    }

    public static ExecutorService getIoExecutorService() {
        return ioExecutorService;
    }

    /**
     * Begin building a request
     * @param context
     * @return
     */
    public LoadBuilder<Builders.Any.B> build(Context context) {
        return new IonRequestBuilder(ContextReference.fromContext(context), this);
    }

    /**
     * Begin building a request
     * @param fragment
     * @return
     */
    public LoadBuilder<Builders.Any.B> build(Fragment fragment) {
        return new IonRequestBuilder(new ContextReference.FragmentContextReference(fragment), this);
    }

    /**
     * Begin building a request
     * @param fragment
     * @return
     */
    public LoadBuilder<Builders.Any.B> build(android.support.v4.app.Fragment fragment) {
        return new IonRequestBuilder(new ContextReference.SupportFragmentContextReference(fragment), this);
    }

    /**
     * Create a builder that can be used to build an network request
     * @param imageView
     * @return
     */
    public Builders.IV.F<? extends Builders.IV.F<?>> build(ImageView imageView) {
        if (Thread.currentThread() != Looper.getMainLooper().getThread())
            throw new IllegalStateException("must be called from UI thread");
        bitmapBuilder.reset();
        bitmapBuilder.ion = this;
        return bitmapBuilder.withImageView(imageView);
    }

    int groupCount(Object group) {
        FutureSet members;
        synchronized (this) {
            members = inFlight.get(group);
        }

        if (members == null)
            return 0;

        return members.size();
    }

    private static Comparator<DeferredLoadBitmap> DEFERRED_COMPARATOR = new Comparator<DeferredLoadBitmap>() {
        @Override
        public int compare(DeferredLoadBitmap lhs, DeferredLoadBitmap rhs) {
            // higher is more recent
            if (lhs.priority == rhs.priority)
                return 0;
            if (lhs.priority < rhs.priority)
                return 1;
            return -1;
        }
    };

    private Runnable processDeferred = new Runnable() {
        @Override
        public void run() {
            if (BitmapFetcher.shouldDeferImageView(Ion.this))
                return;
            ArrayList<DeferredLoadBitmap> deferred = null;
            for (String key: bitmapsPending.keySet()) {
                Object owner = bitmapsPending.tag(key);
                if (owner instanceof DeferredLoadBitmap) {
                    DeferredLoadBitmap deferredLoadBitmap = (DeferredLoadBitmap)owner;
                    if (deferred == null)
                        deferred = new ArrayList<DeferredLoadBitmap>();
                    deferred.add(deferredLoadBitmap);
                }
            }

            if (deferred == null)
                return;
            int count = 0;
            Collections.sort(deferred, DEFERRED_COMPARATOR);
            for (DeferredLoadBitmap deferredLoadBitmap: deferred) {
                bitmapsPending.tag(deferredLoadBitmap.key, null);
                bitmapsPending.tag(deferredLoadBitmap.fetcher.bitmapKey, null);
                deferredLoadBitmap.fetcher.execute();
                count++;
                // do MAX_IMAGEVIEW_LOAD max. this may end up going over the MAX_IMAGEVIEW_LOAD threshhold
                if (count > BitmapFetcher.MAX_IMAGEVIEW_LOAD)
                    return;
            }
        }
    };

    void processDeferred() {
        mainHandler.removeCallbacks(processDeferred);
        mainHandler.post(processDeferred);
    }

    /**
     * Cancel all pending requests associated with the request group
     * @param group
     */
    public void cancelAll(Object group) {
        FutureSet members;
        synchronized (this) {
            members = inFlight.remove(group);
        }

        if (members == null)
            return;

        for (Future future: members.keySet()) {
            if (future != null)
                future.cancel();
        }
    }

    void addFutureInFlight(Future future, Object group) {
        if (group == null || future == null || future.isDone() || future.isCancelled())
            return;

        FutureSet members;
        synchronized (this) {
            members = inFlight.get(group);
            if (members == null) {
                members = new FutureSet();
                inFlight.put(group, members);
            }
        }

        members.put(future, true);
    }

    /**
     * Cancel all pending requests
     */
    public void cancelAll() {
        ArrayList<Object> groups;

        synchronized (this) {
            groups = new ArrayList<Object>(inFlight.keySet());
        }

        for (Object group: groups)
            cancelAll(group);
    }

    /**
     * Cancel all pending requests associated with the given context
     * @param context
     */
    public void cancelAll(Context context) {
        cancelAll((Object)context);
    }

    public int getPendingRequestCount(Object group) {
        synchronized (this) {
            FutureSet members = inFlight.get(group);
            if (members == null)
                return 0;
            int ret = 0;
            for (Future future: members.keySet()) {
                if (!future.isCancelled() && !future.isDone())
                    ret++;
            }
            return ret;
        }
    }

    public void dump() {
        bitmapCache.dump();
        Log.i(logtag, "Pending bitmaps: " + bitmapsPending.size());
        Log.i(logtag, "Groups: " + inFlight.size());
        for (FutureSet futures: inFlight.values()) {
            Log.i(logtag, "Group size: " + futures.size());
        }
    }

    /**
     * Get the application Context object in use by this Ion instance
     * @return
     */
    public Context getContext() {
        return context;
    }

    static class FutureSet extends WeakHashMap<Future, Boolean> {
    }
    // maintain a list of futures that are in being processed, allow for bulk cancellation
    WeakHashMap<Object, FutureSet> inFlight = new WeakHashMap<Object, FutureSet>();

    private void addCookieMiddleware() {
        httpClient.insertMiddleware(cookieMiddleware = new CookieMiddleware(this));
    }

    /**
     * Get or put an item from the cache
     * @return
     */
    public FileCacheStore cache(String key) {
        return new FileCacheStore(this, responseCache.getFileCache(), key);
    }

    public FileCache getCache() {
        return responseCache.getFileCache();
    }

    /**
     * Get or put an item in the persistent store
     * @return
     */
    public FileCacheStore store(String key) {
        return new FileCacheStore(this, storeCache, key);
    }

    public FileCache getStore() {
        return storeCache;
    }

    public String getName() {
        return name;
    }

    /**
     * Get the Cookie middleware that is attached to the AsyncHttpClient instance.
     * @return
     */
    public CookieMiddleware getCookieMiddleware() {
        return cookieMiddleware;
    }

    public ConscryptMiddleware getConscryptMiddleware() {
        return conscryptMiddleware;
    }

    /**
     * Get the AsyncHttpClient object in use by this Ion instance
     * @return
     */
    public AsyncHttpClient getHttpClient() {
        return httpClient;
    }

    /**
     * Get the AsyncServer reactor in use by this Ion instance
     * @return
     */
    public AsyncServer getServer() {
        return httpClient.getServer();
    }

    public class Config {
        public HttpLoader getHttpLoader() {
            return httpLoader;
        }

        public VideoLoader getVideoLoader() {
            return videoLoader;
        }

        public PackageIconLoader getPackageIconLoader() {
            return packageIconLoader;
        }

        public ContentLoader getContentLoader() {
            return contentLoader;
        }

        public FileLoader getFileLoader() {
            return fileLoader;
        }

        public ResponseCacheMiddleware getResponseCache() {
            return responseCache;
        }

        public SSLContext createSSLContext(String algorithm) throws NoSuchAlgorithmException {
            conscryptMiddleware.initialize();
            return SSLContext.getInstance(algorithm);
        }

        /**
         * Get the Gson object in use by this Ion instance.
         * This can be used to customize serialization and deserialization
         * from java objects.
         * @return
         */
        public synchronized Gson getGson() {
            if (gson == null)
                gson = new Gson();
            return gson;
        }

        /**
         * Set the log level for all requests made by Ion.
         * @param logtag
         * @param logLevel
         * @return
         */
        public Config setLogging(String logtag, int logLevel) {
            Ion.this.logtag = logtag;
            Ion.this.logLevel = logLevel;
            return this;
        }

        /**
         * Route all http requests through the given proxy.
         * @param host
         * @param port
         */
        public void proxy(String host, int port) {
            httpClient.getSocketMiddleware().enableProxy(host, port);
        }

        /**
         * Route all https requests through the given proxy.
         * Note that https proxying requires that the Android device has the appropriate
         * root certificate installed to function properly.
         * @param host
         * @param port
         */
        public void proxySecure(String host, int port) {
            httpClient.getSSLSocketMiddleware().enableProxy(host, port);
        }

        /**
         * Disable routing of http requests through a previous provided proxy
         */
        public void disableProxy() {
            httpClient.getSocketMiddleware().disableProxy();
        }

        /**
         * Disable routing of https requests through a previous provided proxy
         */
        public void disableSecureProxy() {
            httpClient.getSocketMiddleware().disableProxy();
        }

        /**
         * Set the Gson object in use by this Ion instance.
         * This can be used to customize serialization and deserialization
         * from java objects.
         * @param gson
         */
        public void setGson(Gson gson) {
            Ion.this.gson = gson;
        }

        AsyncHttpRequestFactory asyncHttpRequestFactory = new AsyncHttpRequestFactory() {
            @Override
            public AsyncHttpRequest createAsyncHttpRequest(Uri uri, String method, Headers headers) {
                AsyncHttpRequest request = new AsyncHttpRequest(uri, method, headers);
                if (!TextUtils.isEmpty(userAgent))
                    request.getHeaders().set("User-Agent", userAgent);
                return request;
            }
        };

        public AsyncHttpRequestFactory getAsyncHttpRequestFactory() {
            return asyncHttpRequestFactory;
        }

        public Config setAsyncHttpRequestFactory(AsyncHttpRequestFactory asyncHttpRequestFactory) {
            this.asyncHttpRequestFactory = asyncHttpRequestFactory;
            return this;
        }

        public String userAgent() {
            return userAgent;
        }

        public Config userAgent(String userAgent) {
            Ion.this.userAgent = userAgent;
            return this;
        }

        public Config addLoader(int index, Loader loader) {
            loaders.add(index, loader);
            return this;
        }
        public Config insertLoader(Loader loader) {
            loaders.add(0, loader);
            return this;
        }
        public Config addLoader(Loader loader) {
            loaders.add(loader);
            return this;
        }
        public List<Loader> getLoaders() {
            return loaders;
        }
    }

    public Config configure() {
        return config;
    }

    /**
     * Return the bitmap cache used by this Ion instance
     * @return
     */
    public IonBitmapCache getBitmapCache() {
        return bitmapCache;
    }
}




Java Source Code List

com.koushikdutta.ion.BitmapCallback.java
com.koushikdutta.ion.BitmapFetcher.java
com.koushikdutta.ion.BitmapInfoToBitmap.java
com.koushikdutta.ion.ContextReference.java
com.koushikdutta.ion.DefaultTransform.java
com.koushikdutta.ion.DeferredLoadBitmap.java
com.koushikdutta.ion.FileCacheStore.java
com.koushikdutta.ion.HeadersCallback.java
com.koushikdutta.ion.HeadersResponse.java
com.koushikdutta.ion.ImageViewBitmapInfo.java
com.koushikdutta.ion.ImageViewFutureImpl.java
com.koushikdutta.ion.InputStreamParser.java
com.koushikdutta.ion.IonBitmapRequestBuilder.java
com.koushikdutta.ion.IonDrawable.java
com.koushikdutta.ion.IonImageViewRequestBuilder.java
com.koushikdutta.ion.IonLog.java
com.koushikdutta.ion.IonRequestBuilder.java
com.koushikdutta.ion.Ion.java
com.koushikdutta.ion.LoadBitmapBase.java
com.koushikdutta.ion.LoadBitmapEmitter.java
com.koushikdutta.ion.LoadBitmapRegion.java
com.koushikdutta.ion.LoadBitmap.java
com.koushikdutta.ion.LoadDeepZoom.java
com.koushikdutta.ion.Loader.java
com.koushikdutta.ion.ProgressCallback.java
com.koushikdutta.ion.RequestBodyUploadObserver.java
com.koushikdutta.ion.Response.java
com.koushikdutta.ion.ScaleMode.java
com.koushikdutta.ion.TransformBitmap.java
com.koushikdutta.ion.bitmap.BitmapDecodeException.java
com.koushikdutta.ion.bitmap.BitmapInfo.java
com.koushikdutta.ion.bitmap.Exif.java
com.koushikdutta.ion.bitmap.IonBitmapCache.java
com.koushikdutta.ion.bitmap.LocallyCachedStatus.java
com.koushikdutta.ion.bitmap.LruBitmapCache.java
com.koushikdutta.ion.bitmap.MarkableInputStream.java
com.koushikdutta.ion.bitmap.PostProcess.java
com.koushikdutta.ion.bitmap.SoftReferenceHashtable.java
com.koushikdutta.ion.bitmap.Transform.java
com.koushikdutta.ion.builder.AnimateGifMode.java
com.koushikdutta.ion.builder.BitmapBuilder.java
com.koushikdutta.ion.builder.BitmapFutureBuilder.java
com.koushikdutta.ion.builder.Builders.java
com.koushikdutta.ion.builder.FutureBuilder.java
com.koushikdutta.ion.builder.GsonFutureBuilder.java
com.koushikdutta.ion.builder.ImageViewBuilder.java
com.koushikdutta.ion.builder.ImageViewFutureBuilder.java
com.koushikdutta.ion.builder.LoadBuilder.java
com.koushikdutta.ion.builder.LoadImageViewFutureBuilder.java
com.koushikdutta.ion.builder.MultipartBodyBuilder.java
com.koushikdutta.ion.builder.RequestBuilder.java
com.koushikdutta.ion.builder.UrlEncodedBuilder.java
com.koushikdutta.ion.conscrypt.ConscryptMiddleware.java
com.koushikdutta.ion.cookie.CookieMiddleware.java
com.koushikdutta.ion.future.ImageViewFuture.java
com.koushikdutta.ion.future.ResponseFuture.java
com.koushikdutta.ion.gif.GifDecoder.java
com.koushikdutta.ion.gif.GifFrame.java
com.koushikdutta.ion.gson.GsonArrayParser.java
com.koushikdutta.ion.gson.GsonBody.java
com.koushikdutta.ion.gson.GsonObjectParser.java
com.koushikdutta.ion.gson.GsonParser.java
com.koushikdutta.ion.gson.GsonSerializer.java
com.koushikdutta.ion.gson.PojoBody.java
com.koushikdutta.ion.loader.AssetLoader.java
com.koushikdutta.ion.loader.AsyncHttpRequestFactory.java
com.koushikdutta.ion.loader.ContentLoader.java
com.koushikdutta.ion.loader.FileLoader.java
com.koushikdutta.ion.loader.HttpLoader.java
com.koushikdutta.ion.loader.InputStreamDataEmitterFuture.java
com.koushikdutta.ion.loader.MediaFile.java
com.koushikdutta.ion.loader.MtpConstants.java
com.koushikdutta.ion.loader.PackageIconLoader.java
com.koushikdutta.ion.loader.ResourceLoader.java
com.koushikdutta.ion.loader.SimpleLoader.java
com.koushikdutta.ion.loader.StreamLoader.java
com.koushikdutta.ion.loader.VideoLoader.java
com.koushikdutta.ion.sample.DeepZoomSample.java
com.koushikdutta.ion.sample.GallerySample.java
com.koushikdutta.ion.sample.GoogleImageSearch.java
com.koushikdutta.ion.sample.ImageViewSample.java
com.koushikdutta.ion.sample.LollipopTransitionFullscreen.java
com.koushikdutta.ion.sample.LollipopTransition.java
com.koushikdutta.ion.sample.ProgressBarDownload.java
com.koushikdutta.ion.sample.ProgressBarUpload.java
com.koushikdutta.ion.sample.SampleApplication.java
com.koushikdutta.ion.sample.Samples.java
com.koushikdutta.ion.sample.SquaredImageView.java
com.koushikdutta.ion.sample.TwitterGson.java
com.koushikdutta.ion.sample.Twitter.java