前言
前面一篇文章简单的介绍了Picasso的使用,已经整个源码调用的流程,过了一遍。但是其中还有很多的细节我们并没有去涉及到。今天在昨天的基础之上再进行深入。
Picasso对象
前面一篇文章我们是从Picasso.get().load("http://i.imgur.com/DvpvklR.png").into(ivTest)
慢慢深入的,这里我们也要找个可以深入的对象,就是最重要的Picasso
对象。
因为我们在使用的时候就是直接Picasso.get().***
这样去调用的,所以说我们先了解下Picasso
所有的api,对整个框架的理解,以及对Picasso
更有效率的使用。
public方法
我们的as很强大,直接左侧栏查看当前类的公用方法.
这里就把方法一个个介绍下。便于大家理解。
- areIndicatorsEnabled(),setIndicatorsEnabled()
@SuppressWarnings("UnusedDeclaration") public void setIndicatorsEnabled(boolean enabled) {
indicatorsEnabled = enabled;
}
@SuppressWarnings("UnusedDeclaration") public boolean areIndicatorsEnabled() {
return indicatorsEnabled;
}
用来设置和获取是否显示当前加载图片的方式,上一篇文章有使用过,就是显示当前图片是由三级缓存中的哪一个加载的。
- cancelRequest
看名字就知道,是直接用来取消请求的。
这里可以深入下。
public void cancelRequest(@NonNull ImageView view) {
if (view == null) {
throw new IllegalArgumentException("view cannot be null.");
}
cancelExistingRequest(view);
}
void cancelExistingRequest(Object target) {
checkMain();
//前面在加载图片的时候是会target-action以key-value的方式保存在targetToAction中,后面我会指出,在哪里保存的。这里直接通过target获取到action,然后cancel
Action action = targetToAction.remove(target);
if (action != null) {
action.cancel();
dispatcher.dispatchCancel(action);
}
//这里就比较有意思,因为第一篇文章我们介绍过,如果是`ImageView`的话,很可能会使用fit方法去适配`ImageView`的宽高,就有使用到DeferredRequestCreator,所以这里要移除
if (target instanceof ImageView) {
ImageView targetImageView = (ImageView) target;
DeferredRequestCreator deferredRequestCreator =
targetToDeferredRequestCreator.remove(targetImageView);
if (deferredRequestCreator != null) {
deferredRequestCreator.cancel();
}
}
}
- cancelTag,pauseTag,resumeTag
这3个一起说,这3个可以说是批量操作符。可以简单的看一下。
Picasso.get().load("http://i.imgur.com/DvpvklR.png")
.tag("test")
.into(ivTest)
Picasso.get()
.load("http://i.imgur.com/DvpvklR.png")
.tag("test")
.into(ivTest2)
Picasso.get().cancelTag("test")
可以先tag标记下每个请求,然后可以批量处理。
分别是取消,暂停,恢复。
- setLoggingEnabled,isLoggingEnabled
public void setLoggingEnabled(boolean enabled) {
loggingEnabled = enabled;
}
public boolean isLoggingEnabled() {
return loggingEnabled;
}
是否启动日志
- getSnapshot
@SuppressWarnings("UnusedDeclaration") public StatsSnapshot getSnapshot() {
return stats.createSnapshot();
}
获取到Picasso
的一个快照。
Picasso.get().snapshot.dump()
然后直接打印。
===============BEGIN PICASSO STATS ===============
Memory Cache Stats
Max Cache Size: 57521883
Cache Size: 0
Cache % Full: 0
Cache Hits: 0
Cache Misses: 0
Network Stats
Download Count: 0
Total Download Size: 0
Average Download Size: 0
Bitmap Stats
Total Bitmaps Decoded: 0
Total Bitmap Size: 0
Total Transformed Bitmaps: 0
Total Transformed Bitmap Size: 0
Average Bitmap Size: 0
Average Transformed Bitmap Size: 0
===============END PICASSO STATS ===============
这个就灰常的方便了,直接看当前Picasso的使用状态
- invalidate
因为Picasso
使用了LruCache
缓存到内存中,key-value与url-bitmap对应起来(实际上不是保存Bitmap,而是自己封装了另外一个类,但是里面是有Bitmap的,这里先不具体)。invalidate可以移除缓存。
public void invalidate(@Nullable Uri uri) {
if (uri != null) {
cache.clearKeyUri(uri.toString());
}
}
- load
这个就不说了,上一篇文章介绍了很多了。
重要对象介绍
上面简单的了Picasso对象,但是还有很多重要的对象。
我们可以从Picasso.Builder
中去寻找,因为这里面都是我们可以配置的对象。
public static class Builder {
private final Context context;
private Downloader downloader;
private ExecutorService service;
private Cache cache;
private Listener listener;
private RequestTransformer transformer;
private List requestHandlers;
private Bitmap.Config defaultBitmapConfig;
private boolean indicatorsEnabled;
private boolean loggingEnabled;
...
这么多可以配置的对象,ndicatorsEnabled,loggingEnabled,context先不说了。
我们来先来简单介绍下另外几个。
- Downloader downloader
默认实现OkHttp3Downloader
@NonNull @Override public Response load(@NonNull Request request) throws IOException { return client.newCall(request).execute();
}
```
其实是可以自己复写,使用自己的http框架
- ExecutorService service
默认实现PicassoExecutorService
//创建了一个线程池,默认都是3个核心线程,然后还有一个有优先级的阻塞队列 PicassoExecutorService() { super(DEFAULT_THREAD_COUNT, DEFAULT_THREAD_COUNT, 0, TimeUnit.MILLISECONDS, new PriorityBlockingQueue
(), new Utils.PicassoThreadFactory());
}
```
这里其实还有一个比较有意思的方法
void adjustThreadCount(NetworkInfo info) {
if (info == null || !info.isConnectedOrConnecting()) {
setThreadCount(DEFAULT_THREAD_COUNT);
return;
}
switch (info.getType()) {
case ConnectivityManager.TYPE_WIFI:
case ConnectivityManager.TYPE_WIMAX:
case ConnectivityManager.TYPE_ETHERNET:
setThreadCount(4);
break;
case ConnectivityManager.TYPE_MOBILE:
switch (info.getSubtype()) {
case TelephonyManager.NETWORK_TYPE_LTE: // 4G
case TelephonyManager.NETWORK_TYPE_HSPAP:
case TelephonyManager.NETWORK_TYPE_EHRPD:
setThreadCount(3);
break;
case TelephonyManager.NETWORK_TYPE_UMTS: // 3G
case TelephonyManager.NETWORK_TYPE_CDMA:
case TelephonyManager.NETWORK_TYPE_EVDO_0:
case TelephonyManager.NETWORK_TYPE_EVDO_A:
case TelephonyManager.NETWORK_TYPE_EVDO_B:
setThreadCount(2);
break;
case TelephonyManager.NETWORK_TYPE_GPRS: // 2G
case TelephonyManager.NETWORK_TYPE_EDGE:
setThreadCount(1);
break;
default:
setThreadCount(DEFAULT_THREAD_COUNT);
}
break;
default:
setThreadCount(DEFAULT_THREAD_COUNT);
}
}
就是会根据网络的情况使用不同的线程数。可以学习下。
也可以自定义
- Cache cache
默认使用LruCache
public LruCache(@NonNull Context context) {
this(Utils.calculateMemoryCacheSize(context));
}
...
static int calculateMemoryCacheSize(Context context) {
ActivityManager am = getService(context, ACTIVITY_SERVICE);
boolean largeHeap = (context.getApplicationInfo().flags & FLAG_LARGE_HEAP) != 0;
int memoryClass = largeHeap ? am.getLargeMemoryClass() : am.getMemoryClass();
// Target ~15% of the available heap.
return (int) (1024L * 1024L * memoryClass / 7);
}
这里也很有意思,根据当前的app所能使用的内存值获取一个比较合适的缓存内存的最大值。自己可以复写调整。
- Listener listener
没有默认值
public interface Listener {
void onImageLoadFailed(Picasso picasso, Uri uri, Exception exception);
}
很显然是用来全局监听图片加载失败的事件。
- RequestTransformer transformer
默认
RequestTransformer IDENTITY = new RequestTransformer() {
@Override public Request transformRequest(Request request) {
return request;
}
};
其实就是一个request的全局的一个转化。默认不转化。
- List
requestHandlers
前面已经介绍过了默认有很多种requestHandlers,也可以自己定义 - Bitmap.Config defaultBitmapConfig
默认为null
在requestHandler里面的createBitmapOptions有使用到
static BitmapFactory.Options createBitmapOptions(Request data) {
final boolean justBounds = data.hasSize();
final boolean hasConfig = data.config != null;
BitmapFactory.Options options = null;
if (justBounds || hasConfig || data.purgeable) {
options = new BitmapFactory.Options();
options.inJustDecodeBounds = justBounds;
options.inInputShareable = data.purgeable;
options.inPurgeable = data.purgeable;
//在这里,如果有config,就配置下,如果没有那么就默认
if (hasConfig) {
options.inPreferredConfig = data.config;
}
}
return options;
}
一共这么多选项,可以选择。
总结
Picasso用起来也挺爽的,后面有空学习下Glide和Fresco做下对比