Volley

如何提升自己

Volley

  • 回忆xutils:快速开发型框架,DbUtils(orm),ViewUtils(ioc),HttpUtils,BitmapUtils

  • 其他的快速开发型框架:andBase,thinkandroid,loonandroid,dhroid

  • orm:对象关系型映射
    • db:create table t_table(_id integer primary key autoincret…);
    • insert–>save(obj)
  • ioc:控制反转
    • Obj obj = new Obj();
    • 对象的实例化,不用new关键字就可以了吧.
  • 为什么要讲volley?
    • 因为它是google出的,google 在2013 i/o大会上提出来的.
    • 而且在几个项目里面已经看到了它的身影
  • google公司为什么会去搞一个volley框架?

    • 1.用户开启一个activity,然后加载网络,这个时候.如果用户点击了finish按钮.activity被销毁了–>网络请求和activity的生命周期是应该联动起来的.

    • 2.listview加载图片的情况比较多.如果用户快速的去滑动listview–>getView->快速的加载图片,用户停止操作的时候.其实真正现实的图片最多就几张—>图片应该缓存起来(内存 +本地 )

    • 3.如果用户打开了一个activity,用户旋转了一下屏幕.activity会旋转–>生命周期重走了–>网络请求缓存

    • 4.之前我们的网络请求,httpurlconnection,httpclient,asynctask(api)–>android sdk–>封装性不够好.1000个开发者就有1000种使用方式–>不够统一

    • 5.理念很容易理解,是开源的.
  • volley是啥?
    • 是一种通信框架,和xutils中的HttpUtils,BitmapUtils

Volley两个核心类

  • Request:一个请求
    • StringRequest:请求的时候直接回来一个String
    • JsonObjectRequest:请求的时候直接回来一个JsonObject
    • JsonArrayRequest:请求的时候直接回来一个JsonArray
    • ImageRequest:请求的时候直接回来一个Bitmap
    • 自定义请求:一会我们会结合gson
  • ImageLoader:图片的加载器
  • NetWorkImageView:继承了imageView,对ImageView进行了拓展
  • RequestQueue:请求队列.

一步一步学习

JsonObject取值

  • String origin = response.getString(“origin”);// 方式一
    • 这个如果没有对应的key会抛异常.需要异常处理
  • String origin = response.optString(“origin”);// 方式二
    • 这个如果没有对应的key不会抛异常.会返回一个默认值
    • optString:默认值”“
    • optInt:默认值 0
    • 比如有的实体bean属性很多.我们不喜欢去建议对应的XXX.class的时候.可以使用JsonObject里面的这个方法;

图片

  • 大图片的处理:

    • 大图片处理的核心
    • 核心类:BitmapFactory.Options
    • 核心方法:

      • decodeOptions.inJustDecodeBounds = true;–>得到图片的宽度以及高度,不需要把图片加载到内存 10M
      • decodeOptions.inJustDecodeBounds = false;–>真正去加载图片
      • decodeOptions.inSampleSize–>采样率–>不同的框架有不同的核心算法
        • 特点:2 4 8 –>取值最好使用2的指数,如果是2,最终效果是1/2*1/
    • 步骤
      1.得到实际的宽度和高度
      2.得到理想的宽度和高度
      3.根据理想的宽度和高度和实际的宽度和高度计算出最好的采样值(inSampleSize)

  • 图片的加载
  • 图片的缓存

框架找inSampleSize的方式

  1. volley:会按照2的指数增长的方式去找

    static int findBestSampleSize(
        int actualWidth, int actualHeight, int desiredWidth, int desiredHeight) {
    double wr = (double) actualWidth / desiredWidth;
    double hr = (double) actualHeight / desiredHeight;
    double ratio = Math.min(wr, hr);
    float n = 1.0f;
    while ((n * 2) <= ratio) {
        n *= 2;
    }
    return (int) n;
    }
    
  2. Xutils

     public static int calculateInSampleSize(BitmapFactory.Options options, int maxWidth, int maxHeight) {
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;
    
    if (width > maxWidth || height > maxHeight) {
        if (width > height) {
            inSampleSize = Math.round((float) height / (float) maxHeight);
        } else {
            inSampleSize = Math.round((float) width / (float) maxWidth);
        }
    
        final float totalPixels = width * height;
    
        final float maxTotalPixels = maxWidth * maxHeight * 2;
    
        while (totalPixels / (inSampleSize * inSampleSize) > maxTotalPixels) {
            inSampleSize++;
        }
    }
    return inSampleSize;
    }
    
  3. uil_imageLoader:做的比较细.会按照不同的scaleType采用不同的算法,而且也是按照了2的指数增长的形式去操作

    int scale;
    if (scaleType == ImageScaleType.NONE) {
        scale = 1;
    } else if (scaleType == ImageScaleType.NONE_SAFE) {
        scale = ImageSizeUtils.computeMinImageSampleSize(imageSize);
    } else {
        ImageSize targetSize = decodingInfo.getTargetSize();
        boolean powerOf2 = scaleType == ImageScaleType.IN_SAMPLE_POWER_OF_2;
        scale = ImageSizeUtils.computeImageSampleSize(imageSize, targetSize, decodingInfo.getViewScaleType(), powerOf2);
    }
    
    if (scale > 1 && loggingEnabled) {
        L.d(LOG_SUBSAMPLE_IMAGE, imageSize, imageSize.scaleDown(scale), scale, decodingInfo.getImageKey());
    }
    
    //隔开
    
    public static int computeMinImageSampleSize(ImageSize srcSize) {
        final int srcWidth = srcSize.getWidth();
        final int srcHeight = srcSize.getHeight();
        final int targetWidth = maxBitmapSize.getWidth();
        final int targetHeight = maxBitmapSize.getHeight();
    
        final int widthScale = (int) Math.ceil((float) srcWidth / targetWidth);
        final int heightScale = (int) Math.ceil((float) srcHeight / targetHeight);
    
        return Math.max(widthScale, heightScale); // max
    }
    
    public static int computeImageSampleSize(ImageSize srcSize,ImageSize targetSize, ViewScaleType viewScaleType,boolean powerOf2Scale) {
            final int srcWidth = srcSize.getWidth();
            final int srcHeight = srcSize.getHeight();
            final int targetWidth = targetSize.getWidth();
            final int targetHeight = targetSize.getHeight();
    
    int scale = 1;
    
    switch (viewScaleType) {
    
        case FIT_INSIDE:
            if (powerOf2Scale) {
                        final int halfWidth = srcWidth / 2;
                        final int halfHeight = srcHeight / 2;
                while ((halfWidth / scale) > targetWidth || (halfHeight / scale) > targetHeight) { // ||
                    scale *= 2;
                }
            } else {
                scale = Math.max(srcWidth / targetWidth, srcHeight / targetHeight); // max
            }
            break;
    
        case CROP:
            if (powerOf2Scale) {
                final int halfWidth = srcWidth / 2;
                final int halfHeight = srcHeight / 2;
                while ((halfWidth / scale) > targetWidth && (halfHeight / scale) > targetHeight) { // &&
                    scale *= 2;
                }
            } else {
                scale = Math.min(srcWidth / targetWidth, srcHeight / targetHeight); // min
            }
            break;
    }
    
    if (scale < 1) {
        scale = 1;
    }
    scale = considerMaxTextureSize(srcWidth, srcHeight, scale, powerOf2Scale);
    
    return scale;
    

    }

内存缓存:集合存对象

  • 1.内存缓存的核心操作:
    • 存:就有很多的考虑
    • 取:唯一索引性
  • 2.选择什么样的存储结构/容器/集合?map

LruCache的使用:

一个内存缓存工具类,提供了基于Lru缓存策略强引用的内存缓存,存储结构使用的LinkedHashmap

LruCache实现原理

  • LinkedHashmap使用

    • LinkedHashmap和Hashmap区别:在构造方法里面多了3个参数
    • 3个参数的意义:
      • initialCapacity:初始化容器大小 16
      • loadFactor:负载因子
      • accessOrder:
        • true:LinkedHash内部会排序–>按照访问顺序排序–>这个也是为什么LruCache使用LinkedHashmap做存储结构的原因
        • false:按照插入顺序去排序
  • LruCache在什么地方可以找到?

    • 在高版本的sdk里面有.
    • 在v4包中有提供.
  • LruCache的使用
    1. 告知缓存的具体大小
    2. 覆写sizeOf方法,
      1. 告知放入LruCache中具体实体的大小
      2. 和maxSize中定义的单位统一

磁盘缓存

可以使用android 2013 i/o大会提供的LruDiskCache

如何使用LruDiskCache

1.初始化好LruDiskCache

    LruDiskCache mDiskLruCache = LruDiskCache.open(diskCacheDir, 1, 1, diskCacheSize);

2.取

LruDiskCache.Snapshot snapshot = mDiskLruCache.get(uri);
FileInputStream in  =  snapshot.getInputStream();
//in-->Bitmap
public static Bitmap decodeStream(InputStream is) 

3.存

LruDiskCache.Editor editor = mDiskLruCache.edit(uri);
FileOutPutStream outputStream = editor.newOutputStream(DISK_CACHE_INDEX);
//bitmap-->outPutStream
public boolean compress(CompressFormat format, int quality, OutputStream stream) 

网络请求的取消

  • httpclient:

    DefaultHttpClient httpClient = new DefaultHttpClient();
    ClientConnectionManager connectionManager = httpClient.getConnectionManager();// 拿到连接管理器
    connectionManager.shutdown();
    
  • volley:多级别取消

    • 取消某一个请求:
    • 取消请求的队列:

      //2. 创建RequestQueue
      RequestQueue queue = Volley.newRequestQueue(MainActivity.this);
      
      //3. 发起请求
      queue.add(stringRequest);
      
      //取消单个请求
      stringRequest.cancel();//取消一个请求
      //取消所有请求
      queue.cancelAll(null);//取消请求队列里面所有的方法
      //取消置顶tag的请求
      queue.cancelAll("tag1");//取消tag为tag1的一个请求
      
      //请求添加tag-->tag的目的就是为了反查
      stringRequest.setTag("tag1");
      //两个不同的请求可以设置同一个tag
      stringRequest.setTag("tag1");
      //  stringRequest1.setTag("tag1");
      
  • xutils:xutils其实也是封装的httpclient,所以网络请求取消的方式和httpClient一样
  • 生命周期的联动

    StringRequest req1 = null;
    StringRequest req2 = null;
    StringRequest req3 = null;
    StringRequest req4 = null;
    StringRequest req5 = null;
    
    req1.setTag(this.getClass().getSimpleName());
    req2.setTag(this.getClass().getSimpleName());
    req3.setTag(this.getClass().getSimpleName());
    req4.setTag(this.getClass().getSimpleName());
    req5.setTag(this.getClass().getSimpleName());
    
    // 取消对应activity里面所有的请求
    RequestQueue queue = VolleyTools.getInstance(MainActivity.this).getQueue();
    queue.cancelAll(this.getClass().getSimpleName());// MainActivity
    

uil imageLoader

  • 3个核心类
  • ImageLoaderConfiguration:imageloader的配置

    • 简单的实例化方式

      `ImageLoaderConfiguration config = ImageLoaderConfiguration.createDefault(getApplicationContext());`
      
    • 自定义复杂的实例化方式

      ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
          .threadPriority(Thread.NORM_PRIORITY - 2)
          .denyCacheImageMultipleSizesInMemory()
          .diskCacheFileNameGenerator(new Md5FileNameGenerator())
          .diskCacheSize(50 * 1024 * 1024) // 50 Mb
          .tasksProcessingOrder(QueueProcessingType.LIFO)
          .writeDebugLogs() // Remove for release app
          .build();
      
  • ImageLoader:图片加载器
  • DisplayImageOptions:显示效果

    • 支持圆角效果
    • 支持淡入淡出效果
  • 步骤

    • 1.在Application子类里面的oncreate(程序的入口方法)方法中,初始化好ImageLoaderConfiguration,可以使用默认的配置也可以使用自定义配置,uil imageloader提供了非常丰富的配置;

    • 2.使用ImageLoader.getInstance()去直接加载图片ImageLoader.getInstance().displayImage(uri, mIv);

    • 3.可以通过DisplayImageOptions创建默认的展示效果.或者自定义展示效果

uil imageloader和其他框架的区别

0.github上starts以及forks

1.丰富的缓存策略,配置比较丰富 差不多30个配置

2.根据imageView的scalType进行计算缩放值 option.insamplesize

3.HTTP(“http”), HTTPS(“https”), FILE(“file”), CONTENT(“content”), ASSETS(“assets”),加载类型比较多

4.提供了丰富的缓存策略
内存缓存
现在我们来看Universal-Image-Loader有哪些内存缓存策略

    1. 只使用的是强引用缓存 
    LruMemoryCache(这个类就是这个开源框架默认的内存缓存类,缓存的是bitmap的强引用,下面我会从源码上面分析这个类)

    2.使用强引用和弱引用相结合的缓存有
    UsingFreqLimitedMemoryCache(如果缓存的图片总量超过限定值,先删除使用频率最小的bitmap)
    LRULimitedMemoryCache(这个也是使用的lru算法,和LruMemoryCache不同的是,他缓存的是bitmap的弱引用)
    FIFOLimitedMemoryCache(先进先出的缓存策略,当超过设定值,先删除最先加入缓存的bitmap)
    LargestLimitedMemoryCache(当超过缓存限定值,先删除最大的bitmap对象)
    LimitedAgeMemoryCache(当 bitmap加入缓存中的时间超过我们设定的值,将其删除)

    3.只使用弱引用缓存
    WeakMemoryCache(这个类缓存bitmap的总大小没有限制,唯一不足的地方就是不稳定,缓存的图片容易被回收


    硬盘缓存
    FileCountLimitedDiscCache(可以设定缓存图片的个数,当超过设定值,删除掉最先加入到硬盘的文件)
    LimitedAgeDiscCache(设定文件存活的最长时间,当超过这个值,就删除该文件)
    TotalSizeLimitedDiscCache(设定缓存bitmap的最大值,当超过这个值,删除最先加入到硬盘的文件)
    UnlimitedDiscCache(这个缓存类没有任何的限制)

5.使用简单

架构

  • b/s架构:绘图说明

  • mvc:设计思想

    • M:model
    • V:view
    • C:Ctroller
  • mvp:设计思想

    • M:model
    • V:View
    • P:Presenter
  • 四层架构:自我总结

    • 数据提供层–>dataProvider:提供数据
    • 数据持久层–>data persistent–>sqlite ,sp,file
    • 业务逻辑层–>servcie logic
    • ui展现层

gzip

一种压缩格式,一种压缩方式,可以对网络传输的数据进行压缩.减少网络传输的大小

  • 为什么需要压缩?

    • 减少体积,提高传输速度,提高用户体验
  • 浏览器发送器请求的过程?

    • 1.发送请求头:Accept-Encoding:gzip
    • 2.服务器压缩数据,返回数据,在响应头里面添加Content-Encoding:gzip
    • 3.客户端,根据Content-Encoding这个响应头,对应解压
      • 有Content-Encoding:gzip–>gzip解压
      • 没有Content-Encoding:gzip–>标准解压
  • app使用gzip压缩
    • 返回的json/xml(文本信息)其实就是个特殊的网页,其实也是可以进行gzip压缩

gzip压缩效果

通过数据,我们得知,文本的压缩率,大概可以达到70%左右.压缩率很高;

gzip压缩的实现

try {
    boolean isGzip = false;
    //1.创建httpclient
    DefaultHttpClient httpClient = new DefaultHttpClient();
    //2.创建get请求
    HttpGet get = new HttpGet("http://httpbin.org/gzip");
    //① 添加请求头 Accept-Encoding:"gzip, deflate"
    get.addHeader("Accept-Encoding", "gzip");
    //3.执行请求
    HttpResponse response = httpClient.execute(get);
    if (response.getStatusLine().getStatusCode() == 200) {
        //② 得到响应头,Content-Encoding:"gzip"
        Header[] headers = response.getHeaders("Content-Encoding");
        for (Header header : headers) {
            if (header.getValue().equals("gzip")) {//后台server把数据进行了gzip压缩
                isGzip = true;
            }
        }
        String result = "";
        HttpEntity entity = response.getEntity();
        //③根据是否使用gzip压缩.采取不同的解压方式
        if (isGzip) {
            //④进行gzip的解压
            GZIPInputStream in = new GZIPInputStream(response.getEntity().getContent());
            //in-->string
            result = convertStreamToString(in);
        } else {
            //4.打印结果
            result = EntityUtils.toString(entity);
        }
        System.out.println("result:" + result);
    }
} catch (Exception e) {
    e.printStackTrace();
}

测试请求的地址

http://httpbin.org

常见的content-type

  • application/x-www-form-urlencoded:表单,key-value
  • multipart/form-data:二进制,file
  • application/json :json,虽然有的服务器直接用text/plain这个请求头没有任何问题.但是很多服务器,必须需要application/json,明确的说.如果是返回json,一定加上application/json,不要用默认的.实际开发遇到了几次这样的问题.或者说.加上这个请求头肯定是万无一失;
  • text/xml :xml
  • text/plain:普通文本,默认类型

模拟请求插件restClient的使用

这个是firefox上的一个插件,对应chrome浏览器叫做postman,这个插件主要用作和服务器开发人员联调协议;

  • key-value:
    • 1.添加head–>Content-Type
    • 2.传递参数:key=value&key=value
  • jsonString
    • 1.添加head
    • 2.传递参数:jsonString
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值