ion学习

[转]http://blog.csdn.net/moonant/article/details/38101039

它所依赖的库

  • androidasync.jar
  • gson.jar
  • android-support-v4.jar

四种常见的 POST 提交数据方式

  • application/x-www-form-urlencoded
  • multipart/form-data
  • application/json
  • text/xml

特点


  • 自动回调UI线程
  • 灵活的api
  • 缓存
  • 管理activity 和service的生命周期
  • 所有操作返回Futures(可取消)

关于图片

  • 支持ListView回收,缓存
  • 继承自 UrlimageViewHelper

ion的几种网络请求


  1. 基本回调

    Ion.with(context)
    .load("http://api.example.com")
    
  2. 参数

    1. json
      .setJsonObjectBody()
      
    2. url 编码

      .setBosyparameter("foo","bar")

    3. 上传文件
      .setMultipartParameter("goop","noop") 
      .setMultipartParameter("filename.zip",new File("/sd/file"))
      
  3. 进度

    .uploadProgressBar(bar)
    
    .progressBar(bar)
    .progressDialog(progressDialog)
    .progress(new callback())
    
  4. 头信息
    setHeader("foo","bar")
    
  5. img -> ImageView
    .withBitmap()
    .placeholder(resId)
    .error(resId)
    .animateLoad(Animation)
    .animateIn(Animation)
    .intoImageView(imageview)
    
  6. 设置返回类型
    .asJsonObject()
    .asString()
    .write(new File("/"))
    
  7. future
    All operations return a custom Future that allows you to specify a callback that runs on completion.

    • 回调
      setCallBack(new FutureCallback<T>(){});
      
    • 阻塞调用
      get();
      
    • 取消
      .cancel();
      .cancelall(tag)
      
    • 返回头信息
      .withResponse()
      
  8. 阻塞
    JsonObject json = Ion.with(context)
    .load("http://example.com/thing.json").asJsonObject().get();
    

    分包


  • src

    • bitmap
    • builder
    • conscrypt
    • cookie
    • future
    • gif
    • gson
    • loader

    AsserLoader
    BitmapCallback 图片回调类, 4个子类
    BitmapFetcher 图片处理?类()
    BitmapInfoToBitmap
    ContextReference
    DeferredLoadBitmap

加载图片

Load an image into an ImageView_

// This is the "long" way to do build an ImageView request... it allows you to set headers, etc.
Ion.with(context)
.load("http://example.com/image.png")
.withBitmap()
.placeholder(R.drawable.placeholder_image)
.error(R.drawable.error_image)
.animateLoad(spinAnimation)
.animateIn(fadeInAnimation)
.intoImageView(imageView);

// but for brevity, use the ImageView specific builder...
Ion.with(imageView)
.placeholder(R.drawable.placeholder_image)
.error(R.drawable.error_image)
.animateLoad(spinAnimation)
.animateIn(fadeInAnimation)
.load("http://example.com/image.png");

The Ion Image load API has the following features: Disk and memory caching Bitmaps are held via weak references so memory is managed very effeciently ListView Adapter recycling support Bitmap transformations via the .transform(Transform) Animate loading and loaded ImageView states DeepZoom for extremely large images

流程

    • LoadBuilder<Builders.Any.B> Ion.with(Context)

      Get the default Ion object instance and begin building a request

    • Builders.Any.B load(java.lang.String uri) //*返回IonRequestBuilder实现*

      uri - Uri to load. This may be a http(s), file, or content uri.

    • Builders.Any.B load(java.lang.String method, java.lang.String url)

      method - HTTP method such as GET or POST.
      url - Url to load.

    • Builders.Any.B load(java.io.File file)

      file - File to load.

    • Builders.Any.BF<? extends Builders.Any.BF<?>> withBitmap() //继承自builder.FutureBuilder

      Use the request as a Bitmap which can then be modified and/or applied to an ImageView.

  1. Builders.IV.F<? extends Builders.IV.F<?>> Ion.with(ImageView) // 实现类IonImageViewRequestBuilder

    Create a ImageView bitmap request builder

    Builders.Any.BF<? extends Builders.Any.BF<?>>
    Builders.IV.F<? extends Builders.IV.F<?>>
    都是和image bitmap 相关的接口

  2. ImageViewBuilder<I extends ImageViewBuilder<?>> 对 imageView 进行设置
    .placeHolder() .error .animateLoad() .animateIn() 返回 I 可以重复调用

    • 设置ImageView
      ImageViewFuture .intoimageView() //ImageViewFutureBuilder 实现IonBitmapRequestBuilder, IonImageViewRequestBuilder, IonRequestBuilder
    • 设置 uri
      ImageViewFuture .load(url) //LoadImageViewFutureBuilder 实现IonImageViewRequestBuilder
  3. 得到ImageViewFuture(com.koushikdutta.async.future.Cancellable, java.util.concurrent.Future<ImageView>) 实现:IonDrawable.ImageViewFutureImpl

    限定符和类型 方法和说明
    com.koushikdutta.async.future.Future<ImageViewBitmapInfo> withBitmapInfo()
    从接口继承的方法 com.koushikdutta.async.future.Future
    setCallback, then
    从接口继承的方法 com.koushikdutta.async.future.Cancellable
    cancel, isCancelled, isDone
    从接口继承的方法 java.util.concurrent.Future
    cancel, get, get, isCancelled, isDone

Ion

public class Ion {
    public static LoadBuilder<Builders.Any.B> with(Context context) {
        return getDefault(context).build(context);
    }
    public static Ion getDefault(Context context) {
        return getInstance(context, "ion");
    }
   public LoadBuilder<Builders.Any.B> build(Context context) {
        return new IonRequestBuilder(ContextReference.fromContext(context), this);
    }
}

IonRequestBuilder

LoadBuilder<Builders.Any.B> Ion.with(Context)
LoadBuilder<Builders.Any.B>的唯一实现类IonRequestBuilder
Builders.Any.B .load(java.lang.String uri)
返回自己,Builders.Any.B的唯一实现类IonRequestBuilder
Builders.Any.BF<? extends Builders.Any.BF<?>> withBitmap()
返回IonImageViewRequestBuilder,Builders.Any.BF<? extends Builders.Any.BF<?>>两个实现类
IonBitmapRequestBuilder, IonImageViewRequestBuilder

class IonRequestBuilder implements Builders.Any.B LoadBuilder<Builders.Any.B> {
     public IonRequestBuilder load(String url) {
        return loadInternal(AsyncHttpGet.METHOD, url);
    }
     private IonRequestBuilder loadInternal(String method, String url) {
        this.method = method;
        if (!TextUtils.isEmpty(url) && url.startsWith("/"))
            url = new File(url).toURI().toString();
        this.uri = url;
        return this;
    }
     public IonImageViewRequestBuilder withBitmap() {
        return new IonImageViewRequestBuilder(this);
    }
}

IonImageViewRequestBuilder

class IonImageViewRequestBuilder extends IonBitmapRequestBuilder implements Builders.Any.BF<? extends Builders.Any.BF<?>>{
     public IonImageViewRequestBuilder(IonRequestBuilder builder) {
        super(builder);
    }
        @Override
    public ImageViewFuture intoImageView(ImageView imageView) {
        assert Thread.currentThread() == Looper.getMainLooper().getThread();
        if (imageView == null)
            throw new NullPointerException("imageView");

        // no uri? just set a placeholder and bail
        if (builder.uri == null) {
            setIonDrawable(imageView, null, 0).cancel();
            return FUTURE_IMAGEVIEW_NULL_URI;
        }

        // executeCache the request, see if we get a bitmap from cache.
        BitmapFetcher bitmapFetcher = executeCache();// 
        if (bitmapFetcher.info != null) {
            doAnimation(imageView, null, 0);
            IonDrawable drawable = setIonDrawable(imageView, bitmapFetcher.info, Loader.LoaderEmitter.LOADED_FROM_MEMORY);
            drawable.cancel();
            IonDrawable.ImageViewFutureImpl imageViewFuture = drawable.getFuture();
            imageViewFuture.reset();
            imageViewFuture.setComplete(bitmapFetcher.info.exception, imageView);
            return imageViewFuture;
        }

        IonDrawable drawable = setIonDrawable(imageView, null, 0);
        doAnimation(imageView, loadAnimation, loadAnimationResource);
        IonDrawable.ImageViewFutureImpl imageViewFuture = drawable.getFuture();
        imageViewFuture.reset();
        drawable.register(ion, bitmapFetcher.bitmapKey);

        // nothing from cache, check to see if there's too many imageview loads
        // already in progress
        if (BitmapFetcher.shouldDeferImageView(ion)) {
            bitmapFetcher.defer();
        }
        else {
            bitmapFetcher.execute();
        }

        return imageViewFuture;
    }
    private IonDrawable setIonDrawable(ImageView imageView, BitmapInfo info, int loadedFrom) {
        IonDrawable ret = IonDrawable.getOrCreateIonDrawable(imageView)
        .ion(ion)
        .setBitmap(info, loadedFrom)
        .setSize(resizeWidth, resizeHeight)
        .setError(errorResource, errorDrawable)
        .setPlaceholder(placeholderResource, placeholderDrawable)
        .setInAnimation(inAnimation, inAnimationResource)
        .setDisableFadeIn(disableFadeIn);
        imageView.setImageDrawable(ret);
        return ret;
    }

}

IonDrawable

class IonDrawble extends Drawable {
        static IonDrawable getOrCreateIonDrawable(ImageView imageView) {
        Drawable current = imageView.getDrawable();
        IonDrawable ret;
        if (current == null || !(current instanceof IonDrawable))
            ret = new IonDrawable(imageView.getResources(), imageView);
        else
            ret = (IonDrawable)current;
        // invalidate self doesn't seem to trigger the dimension check to be called by imageview.
        // are drawable dimensions supposed to be immutable?
        imageView.setImageDrawable(null);
        return ret;
    }
    public IonDrawable(Resources resources, ImageView imageView) {
        this.resources = resources;
        paint = new Paint(DEFAULT_PAINT_FLAGS);
        callback = new IonDrawableCallback(this, imageView);
    }
    public void register(Ion ion, String bitmapKey) {
        String previousKey = callback.bitmapKey;
        if (TextUtils.equals(previousKey, bitmapKey))
            return;
        callback.bitmapKey = bitmapKey;
        ion.bitmapsPending.add(bitmapKey, callback);
        unregister(ion, previousKey, callback);
    }
}
// create an internal static class that can act as a callback.
    // dont let it hold strong references to anything.
    static class IonDrawableCallback implements FutureCallback<BitmapInfo> {
        private WeakReference<IonDrawable> ionDrawableRef;
        private ContextReference.ImageViewContextReference imageViewRef;
        private String bitmapKey;
        private ImageViewFutureImpl imageViewFuture = new ImageViewFutureImpl();
        private Animation inAnimation;
        private int inAnimationResource;

        public IonDrawableCallback(IonDrawable drawable, ImageView imageView) {
            ionDrawableRef = new WeakReference<IonDrawable>(drawable);
            imageViewRef = new ContextReference.ImageViewContextReference(imageView);
        }

        @Override
        public void onCompleted(Exception e, BitmapInfo result) {
            assert Thread.currentThread() == Looper.getMainLooper().getThread();
            assert result != null;
            // see if the imageview is still alive and cares about this result
            ImageView imageView = imageViewRef.get();
            if (imageView == null)
                return;

            IonDrawable drawable = ionDrawableRef.get();
            if (drawable == null)
                return;

            if (imageView.getDrawable() != drawable)
                return;

            imageView.setImageDrawable(null);
            drawable.setBitmap(result, result.loadedFrom);
            imageView.setImageDrawable(drawable);
            IonBitmapRequestBuilder.doAnimation(imageView, inAnimation, inAnimationResource);

            if (null != imageViewRef.isAlive()) {
                imageViewFuture.cancelSilently();
                return;
            }

            imageViewFuture.setComplete(e, imageView);
        }
    }

IonBitmapRequestBuilder

class IonBitmapRequestBuilder {
    BitmapFetcher executeCache() {
        final String downloadKey = computeDownloadKey();
        String bitmapKey = computeBitmapKey(downloadKey);

        // TODO: eliminate this allocation?
        BitmapFetcher ret = new BitmapFetcher();
        ret.downloadKey = downloadKey;
        ret.bitmapKey = bitmapKey;
        ret.hasTransforms = hasTransforms();
        ret.resizeWidth = resizeWidth;
        ret.resizeHeight = resizeHeight;
        ret.builder = builder;
        ret.transforms = transforms;
        ret.animateGif = animateGif;
        ret.deepZoom = deepZoom;
        ret.postProcess = postProcess;

        // see if this request can be fulfilled from the cache
        if (!builder.noCache) {
            BitmapInfo bitmap = builder.ion.bitmapCache.get(bitmapKey);
            if (bitmap != null) {
                ret.info = bitmap;
                return ret;
            }
        }

        return ret;
    }
}

BitmapFetcher

class BitmapFetcher implements IonRequestBuilder.LoadRequestCallback{
    public static boolean shouldDeferImageView(Ion ion) {
        if (ion.bitmapsPending.keySet().size() <= MAX_IMAGEVIEW_LOAD)
            return false;
        int loadCount = 0;
        for (String key: ion.bitmapsPending.keySet()) {
            Object owner = ion.bitmapsPending.tag(key);
            if (owner instanceof LoadBitmapBase) {
                loadCount++;
                if (loadCount > MAX_IMAGEVIEW_LOAD)
                    return true;
            }
        }
        return false;
    }

    public DeferredLoadBitmap defer() {
        DeferredLoadBitmap ret = new DeferredLoadBitmap(builder.ion, downloadKey, this);
        executeTransforms(builder.ion);
        return ret;
    }

    public void execute() {
        final Ion ion = builder.ion;

        // bitmaps that were transformed are put into the FileCache to prevent
        // subsequent retransformation. See if we can retrieve the bitmap from the disk cache.
        // See TransformBitmap for where the cache is populated.
        FileCache fileCache = ion.responseCache.getFileCache();
        if (!builder.noCache && hasTransforms && fileCache.exists(bitmapKey) && !deepZoom) {
            TransformBitmap.getBitmapSnapshot(ion, bitmapKey, postProcess);
            return;
        }

        // Perform a download as necessary.
        if (ion.bitmapsPending.tag(downloadKey) == null && !fastLoad(builder.uri)) {
            builder.setHandler(null);
            builder.loadRequestCallback = this;

            if (!deepZoom) {
                IonRequestBuilder.EmitterTransform<ByteBufferList> emitterTransform = builder.execute(new ByteBufferListParser(), new Runnable() {
                    @Override
                    public void run() {
                        AsyncServer.post(Ion.mainHandler, new Runnable() {
                            @Override
                            public void run() {
                                ion.bitmapsPending.remove(downloadKey);
                            }
                        });
                    }
                });
                emitterTransform.setCallback(new LoadBitmap(ion, downloadKey, !hasTransforms, resizeWidth, resizeHeight, animateGif, emitterTransform));
            }
            else {
//                System.out.println("downloading file for deepZoom");
                File file = fileCache.getTempFile();
                IonRequestBuilder.EmitterTransform<File> emitterTransform = builder.write(file);
                LoadDeepZoom loadDeepZoom = new LoadDeepZoom(ion, downloadKey, animateGif, emitterTransform, fileCache) {
                    @Override
                    public void onCompleted(Exception e, File file) {
                        super.onCompleted(e, file);
                    }
                };
                emitterTransform.setCallback(loadDeepZoom);
            }
        }

        executeTransforms(ion);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值