Picasso Okhttp3 缓存优化

来源:互联网 发布:淘宝的账号管理在哪里 编辑:程序博客网 时间:2024/05/22 03:11

Picasso本身并没有去“实现”本地缓存功能,而是让网络请求层去缓存http响应,其网络请求逻辑在picasso中对应的是DownLoader接口的实现。

  • 配置gradle
    compile 'com.squareup.okhttp3:okhttp:3.9.0'    compile 'com.squareup.okhttp3:logging-interceptor:3.9.0'    compile 'com.squareup.picasso:picasso:2.5.2'
  • 定义OKhttp3.0+ 版本的DownLoader
import android.net.Uri;import com.squareup.picasso.Downloader;import com.squareup.picasso.NetworkPolicy;import java.io.IOException;import okhttp3.Cache;import okhttp3.CacheControl;import okhttp3.OkHttpClient;import okhttp3.Request;import okhttp3.ResponseBody;public class ImageDownLoader implements Downloader{    OkHttpClient client = null;    public ImageDownLoader(OkHttpClient client)    {        this.client = client;    }    @Override    public Response load(Uri uri, int networkPolicy) throws IOException    {        CacheControl cacheControl = null;        if (networkPolicy != 0)        {            if (NetworkPolicy.isOfflineOnly(networkPolicy))            {                cacheControl = CacheControl.FORCE_CACHE;            }            else            {                CacheControl.Builder builder = new CacheControl.Builder();                if (!NetworkPolicy.shouldReadFromDiskCache(networkPolicy))                {                    builder.noCache();                }                if (!NetworkPolicy.shouldWriteToDiskCache(networkPolicy))                {                    builder.noStore();                }                cacheControl = builder.build();            }        }        Request.Builder builder = new Request.Builder().url(uri.toString());        if (cacheControl != null)        {            builder.cacheControl(cacheControl);        }        okhttp3.Response response = client.newCall(builder.build()).execute();        int responseCode = response.code();        if (responseCode >= 300)        {            response.body().close();            throw new ResponseException(responseCode + " " + response.message(), networkPolicy,                    responseCode);        }        boolean fromCache = response.cacheResponse() != null;        ResponseBody responseBody = response.body();        return new Response(responseBody.byteStream(), fromCache, responseBody.contentLength());    }    @Override    public void shutdown()    {        Cache cache = client.cache();        if (cache != null)        {            try            {                cache.close();            }            catch (IOException ignored)            {            }        }    }}
  • 设置拦截器

在服务端的响应头里加上Cache-Control 如Cache-Control:
max-age=3600,3600表示缓存有效时间为1个小时,即在1个小时之内再次请求同一个url都不会访问网络,在有无网络的情况下都读取缓存,此时,如果想请求最新的内容,应该在构造request的时候使用CacheControl的noCache来实现

我们可以用okhttp的拦截器Interceptor来实现在本地修改响应头的内容,甚至可以在里面判断wifi,4g,3g来实现不同的缓存策略。

import android.content.Context;import android.util.Log;import com.gaoyy.mishop.util.NetworkUtils;import java.io.IOException;import okhttp3.CacheControl;import okhttp3.Interceptor;import okhttp3.Request;import okhttp3.Response;/** * Created by gaoyy on 2017/12/18 0018. */public class CacheInterceptor implements Interceptor{    private Context context;    public CacheInterceptor(Context context)    {        this.context = context;    }    @Override    public Response intercept(Chain chain) throws IOException    {        Log.d("tag", "Intercept respone");        Request request = chain.request();        //如果没有网络,则启用 FORCE_CACHE        if (!NetworkUtils.isNetworkConnected(context))        {            request = request.newBuilder()                    .cacheControl(CacheControl.FORCE_CACHE)                    .build();        }        Response originalResponse = chain.proceed(request);        if (NetworkUtils.isNetworkConnected(context))        {            //有网的时候读接口上的@Headers里的配置            Log.d("tag", "code " + originalResponse.code());            String cacheControl = request.cacheControl().toString();            return originalResponse.newBuilder()                    .header("Cache-Control", cacheControl)                    .removeHeader("Pragma")                    .build();        }        else        {            return originalResponse.newBuilder()                    .header("Cache-Control", "public, only-if-cached, max-stale=3600")                    .removeHeader("Pragma")                    .build();        }    }}
  • 在Application中进行配置

    private void initPicasso(){    File file = new File(this.getCacheDir(),"Picasso");    OkHttpClient client =new OkHttpClient            .Builder()            .addInterceptor(new CacheInterceptor(this))            .cache(new Cache(file, 1024 * 1024 * 100))            .build();    Picasso picasso = new Picasso.Builder(this)            .defaultBitmapConfig(Bitmap.Config.RGB_565)            .downloader(new ImageDownLoader(client))            .indicatorsEnabled(true)            .build();    Picasso.setSingletonInstance(picasso);}

    同样也可以对Retrofit进行使用

    public static void init(Context context){    // 指定缓存路径,缓存大小100Mb    Cache cache = new Cache(new File(context.getCacheDir(), "HttpCache"),            1024 * 1024 * 100);    OkHttpClient okHttpClient = new OkHttpClient.Builder()            .cache(cache)            .retryOnConnectionFailure(true)            .connectTimeout(1500000, TimeUnit.MILLISECONDS)            .writeTimeout(2000000, TimeUnit.MILLISECONDS)            .readTimeout(2000000, TimeUnit.MILLISECONDS)            .addInterceptor(new CacheInterceptor(context))            .addNetworkInterceptor(new CacheInterceptor(context))            .build();    Retrofit apiRetrofit = new Retrofit.Builder()            .baseUrl(Constant.API_BASE)            .client(okHttpClient)            .addConverterFactory(GsonConverterFactory.create())            .build();    sApiService = apiRetrofit.create(Api.class);}

参考:
http://www.jianshu.com/p/6241950f9daf
http://www.jianshu.com/p/093ca3c1447d

原创粉丝点击