Rinsing The Brush: Picasso 3.0 (Chicago Roboto 2018)

Rinsing The Brush: Picasso 3.0 (Chicago Roboto 2018)

Picasso is a powerful image downloading and caching library for Android but since its launch in 2013, other libraries have improved or entered the scene and new requirements have come up.

In this talk, we’ll:

* Dig into the internals of Picasso works
* Compare and contrast to other image libraries
* Discuss latest improvements as we push to 3.0
* …and more!

You’ll learn to efficiently work with different image formats across millions of devices!

Presented with John Rodriguez.

Video: soon!

E68309f117985270285ade8082f4877d?s=128

Jake Wharton

April 13, 2018
Tweet

Transcript

  1. 2.
  2. 3.
  3. 4.
  4. 5.
  5. 6.
  6. 12.

    • Android P • OkHttp 2.x => 3.x
 • Okio

    integration
 • Improvements 3.x Goals
  7. 13.

    • Android P • OkHttp 2.x => 3.x
 • Okio

    integration
 • Improvements 3.x Goals
  8. 14.
  9. 15.
  10. 16.

    Bitmap decodeStreamPreP(Request r, BufferedSource bs) { BitmapFactory.Options options = createBitmapOptions(request);

    if (requiresInSampleSize(options)) { InputStream stream = new SourceBufferingInputStream(bs); BitmapFactory.decodeStream(stream, null, options); calculateInSampleSize(r.targetWidth, r.targetHeight, options, r); } return BitmapFactory.decodeStream(bs.inputStream(), null, options); }
  11. 17.

    Bitmap decodeStreamPreP(Request r, BufferedSource bs) { BitmapFactory.Options options = createBitmapOptions(request);

    if (requiresInSampleSize(options)) { InputStream stream = new SourceBufferingInputStream(bs); BitmapFactory.decodeStream(stream, null, options); calculateInSampleSize(r.targetWidth, r.targetHeight, options, r); } return BitmapFactory.decodeStream(bs.inputStream(), null, options); }
  12. 18.
  13. 19.

    Bitmap decodeStreamP(Request r, BufferedSource bs) { ImageDecoder.Source imageSource = ImageDecoder.createSource(ByteBuffer.wrap(bs.readByteArray()));

    return ImageDecoder.decodeBitmap( imageSource, new OnHeaderDecodedListener() { void onHeaderDecoded(ImageDecoder d, ImageInfo info, Source src) { if (r.hasSize()) { d.setTargetSize(r.targetWidth, r.targetHeight); } } }); }
  14. 20.

    Bitmap decodeStreamP(Request r, BufferedSource bs) { ImageDecoder.Source imageSource = ImageDecoder.createSource(ByteBuffer.wrap(bs.readByteArray()));

    return ImageDecoder.decodeBitmap( imageSource, new OnHeaderDecodedListener() { void onHeaderDecoded(ImageDecoder d, ImageInfo info, Source src) { if (r.hasSize()) { d.setTargetSize(r.targetWidth, r.targetHeight); } } }); }
  15. 21.

    Bitmap decodeStreamP(Request r, BufferedSource bs) { ImageDecoder.Source imageSource = ImageDecoder.createSource(ByteBuffer.wrap(bs.readByteArray()));

    return ImageDecoder.decodeBitmap( imageSource, new OnHeaderDecodedListener() { void onHeaderDecoded(ImageDecoder d, ImageInfo info, Source src) { if (r.hasSize()) { d.setTargetSize(r.targetWidth, r.targetHeight); } } }); }
  16. 22.

    • Android P • OkHttp 2.x => 3.x
 • Okio

    integration
 • Improvements 3.x Goals
  17. 23.
  18. 38.

    • Android P • OkHttp 2.x => 3.x
 • Okio

    integration
 • Improvements 3.x Goals
  19. 39.

    java.io.IOException: Cannot reset at com.squareup.picasso.MarkableInputStream.reset(MarkableInputStream.java:99) at com.squareup.picasso.BitmapHunter.decodeStream(BitmapHunter.java:140) at com.squareup.picasso.BitmapHunter.hunt(BitmapHunter.java:217) at

    com.squareup.picasso.BitmapHunter.run(BitmapHunter.java:159) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:457) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636) at java.lang.Thread.run(Thread.java:764) at com.squareup.picasso.Utils$PicassoThread.run(Utils.java:411)
  20. 43.

    PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA

    PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA METADATA METADATA METADATA MAGIC nightmare_shrek.png
  21. 44.

    PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA

    PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA METADATA METADATA METADATA MAGIC
  22. 45.

    PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA

    PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA METADATA METADATA METADATA MAGIC
  23. 46.

    PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA

    PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA METADATA METADATA METADATA MAGIC
  24. 47.

    PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA

    PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA METADATA METADATA METADATA MAGIC
  25. 48.

    PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA

    PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA METADATA METADATA METADATA MAGIC
  26. 49.

    PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA

    PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA METADATA METADATA METADATA MAGIC
  27. 50.

    InputStream PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL

    DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA METADATA METADATA METADATA MAGIC
  28. 83.

    BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA METADATA PIXEL DATA MarkableInputStream MAGIC

    METADATA METADATA METADATA PIXEL DATA 1920x1080 BitmapFactory MAGIC METADATA METADATA METADATA PIXEL DATA
  29. 84.

    BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA METADATA PIXEL DATA MarkableInputStream MAGIC

    METADATA METADATA METADATA PIXEL DATA 1920x1080 MAGIC METADATA METADATA METADATA PIXEL DATA BitmapFactory
  30. 86.

    PIXEL DATA PIXEL DATA PIXEL DATA BitmapFactory inJustDecodeBounds=true MarkableInputStream MAGIC

    METADATA METADATA METADATA PIXEL DATA 1920x1080 BitmapFactory
  31. 87.

    PIXEL DATA PIXEL DATA PIXEL DATA BitmapFactory inJustDecodeBounds=true MarkableInputStream MAGIC

    METADATA METADATA METADATA PIXEL DATA 1920x1080 BitmapFactory PIXEL DATA PIXEL DATA PIXEL DATA
  32. 104.

    MarkableInputStream BitmapFactory inJustDecodeBounds=true ??? BitmapFactory java.io.IOException: Cannot reset at com.squareup.picasso.MarkableInputStream.reset(MarkableInputStream.java:99)

    at com.squareup.picasso.BitmapHunter.decodeStream(BitmapHunter.java:140) at com.squareup.picasso.BitmapHunter.hunt(BitmapHunter.java:217) at com.squareup.picasso.BitmapHunter.run(BitmapHunter.java:159) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:457) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636) at java.lang.Thread.run(Thread.java:764) at com.squareup.picasso.Utils$PicassoThread.run(Utils.java:411)
  33. 119.

    BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 2PIXEL DATA2 3PIXEL DATA3 4PIXEL DATA4

    1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC offset: 1024 2PIXEL DATA2 3PIXEL DATA3 4PIXEL DATA4 2048
  34. 120.

    BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 2PIXEL DATA2 3PIXEL DATA3 4PIXEL DATA4

    1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC offset: 2048 2PIXEL DATA2 3PIXEL DATA3 4PIXEL DATA4 1024
  35. 121.

    BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 2PIXEL DATA2 3PIXEL DATA3 4PIXEL DATA4

    1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC offset: 2048 2PIXEL DATA2 3PIXEL DATA3 4PIXEL DATA4
  36. 123.

    BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 2PIXEL DATA2 3PIXEL DATA3 4PIXEL DATA4

    5PIXEL DATA5 6PIXEL DATA6 7PIXEL DATA7 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC offset: 2048
  37. 124.

    BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 2PIXEL DATA2 3PIXEL DATA3 4PIXEL DATA4

    5PIXEL DATA5 6PIXEL DATA6 7PIXEL DATA7 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC offset: 2048 5PIXEL DATA5 6PIXEL DATA6 7PIXEL DATA7 3072
  38. 125.

    BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 2PIXEL DATA2 3PIXEL DATA3 4PIXEL DATA4

    5PIXEL DATA5 6PIXEL DATA6 7PIXEL DATA7 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC offset: 3072 5PIXEL DATA5 6PIXEL DATA6 7PIXEL DATA7 2048
  39. 126.

    BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 2PIXEL DATA2 3PIXEL DATA3 4PIXEL DATA4

    5PIXEL DATA5 6PIXEL DATA6 7PIXEL DATA7 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC offset: 3072 5PIXEL DATA5 6PIXEL DATA6 7PIXEL DATA7
  40. 127.

    BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 2PIXEL DATA2 3PIXEL DATA3 4PIXEL DATA4

    5PIXEL DATA5 6PIXEL DATA6 7PIXEL DATA7 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC offset: 3072
  41. 128.

    BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 2PIXEL DATA2 3PIXEL DATA3 4PIXEL DATA4

    5PIXEL DATA5 6PIXEL DATA6 7PIXEL DATA7 8PIXEL DATA8 9PIXEL DATA9 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC offset: 3072
  42. 129.

    BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 2PIXEL DATA2 3PIXEL DATA3 4PIXEL DATA4

    5PIXEL DATA5 6PIXEL DATA6 7PIXEL DATA7 8PIXEL DATA8 9PIXEL DATA9 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC offset:x3072 8PIXEL DATA8 9PIXEL DATA9 3754
  43. 130.

    BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 2PIXEL DATA2 3PIXEL DATA3 4PIXEL DATA4

    5PIXEL DATA5 6PIXEL DATA6 7PIXEL DATA7 8PIXEL DATA8 9PIXEL DATA9 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC offset: 3754 8PIXEL DATA8 9PIXEL DATA9 x3072
  44. 131.

    BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 2PIXEL DATA2 3PIXEL DATA3 4PIXEL DATA4

    5PIXEL DATA5 6PIXEL DATA6 7PIXEL DATA7 8PIXEL DATA8 9PIXEL DATA9 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC offset: 3754 8PIXEL DATA8 9PIXEL DATA9
  45. 132.

    BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 2PIXEL DATA2 3PIXEL DATA3 4PIXEL DATA4

    5PIXEL DATA5 6PIXEL DATA6 7PIXEL DATA7 8PIXEL DATA8 9PIXEL DATA9 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC offset: 3754
  46. 133.

    BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 2PIXEL DATA2 3PIXEL DATA3 4PIXEL DATA4

    5PIXEL DATA5 6PIXEL DATA6 7PIXEL DATA7 8PIXEL DATA8 9PIXEL DATA9 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC offset: 3754 ???
  47. 134.

    BufferedSource 2PIXEL DATA2 3PIXEL DATA3 4PIXEL DATA4 5PIXEL DATA5 6PIXEL

    DATA6 7PIXEL DATA7 8PIXEL DATA8 9PIXEL DATA9 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC offset: 3754 ??? BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream
  48. 135.

    BitmapFactory InputStream BufferedSource 2PIXEL DATA2 3PIXEL DATA3 4PIXEL DATA4 5PIXEL

    DATA5 6PIXEL DATA6 7PIXEL DATA7 8PIXEL DATA8 9PIXEL DATA9 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream
  49. 136.

    BitmapFactory InputStream BufferedSource 2PIXEL DATA2 3PIXEL DATA3 4PIXEL DATA4 5PIXEL

    DATA5 6PIXEL DATA6 7PIXEL DATA7 8PIXEL DATA8 9PIXEL DATA9 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream
  50. 137.

    BitmapFactory InputStream BufferedSource 2PIXEL DATA2 3PIXEL DATA3 4PIXEL DATA4 5PIXEL

    DATA5 6PIXEL DATA6 7PIXEL DATA7 8PIXEL DATA8 9PIXEL DATA9 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream
  51. 138.

    BitmapFactory InputStream BufferedSource 2PIXEL DATA2 3PIXEL DATA3 4PIXEL DATA4 5PIXEL

    DATA5 6PIXEL DATA6 7PIXEL DATA7 8PIXEL DATA8 9PIXEL DATA9 BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream
  52. 139.

    BitmapFactory InputStream BufferedSource 5PIXEL DATA5 6PIXEL DATA6 7PIXEL DATA7 8PIXEL

    DATA8 9PIXEL DATA9 BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream
  53. 148.
  54. 149.

    ExifInterface BufferedSource SourceBufferingInputStream 1METADATA1 MAGIC 1METADATA1 MAGIC offset: 341 BitmapFactory

    inJustDecodeBounds=true SourceBufferingInputStream 1920x1080 offset: 341 1METADATA1 MAGIC
  55. 150.

    ExifInterface BufferedSource SourceBufferingInputStream 1METADATA1 MAGIC 1METADATA1 MAGIC offset: 341 BitmapFactory

    inJustDecodeBounds=true SourceBufferingInputStream 1920x1080 offset: 341 1METADATA1 MAGIC
  56. 151.

    ExifInterface BufferedSource SourceBufferingInputStream 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC 1METADATA1

    MAGIC offset: 341 BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream 1920x1080 offset: 341
  57. 152.

    ExifInterface BufferedSource SourceBufferingInputStream 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC 1METADATA1

    MAGIC offset: 341 BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream 1920x1080 offset: 1024 1PIXEL DATA1 3METADATA3 2METADATA2 341
  58. 153.

    ExifInterface BufferedSource SourceBufferingInputStream 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC 1METADATA1

    MAGIC offset: 341 BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream 1920x1080 offset: 1024 1PIXEL DATA1 3METADATA3 2METADATA2 341
  59. 154.

    ExifInterface BufferedSource SourceBufferingInputStream 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC 1METADATA1

    MAGIC offset: 341 BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream 1920x1080 offset: 1024 1PIXEL DATA1 3METADATA3 2METADATA2 341 90°
  60. 155.

    BufferedSource 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC 1METADATA1 MAGIC offset:

    341 BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream 1920x1080 offset: 1024 1PIXEL DATA1 3METADATA3 2METADATA2 341 90° ExifInterface SourceBufferingInputStream
  61. 156.

    BitmapFactory InputStream BufferedSource 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC 1METADATA1

    MAGIC offset: 341 BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream 1920x1080 offset: 1024 1PIXEL DATA1 3METADATA3 2METADATA2 341 90° ExifInterface SourceBufferingInputStream
  62. 157.

    BitmapFactory InputStream BufferedSource 2PIXEL DATA2 3PIXEL DATA3 4PIXEL DATA4 1PIXEL

    DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC 1METADATA1 MAGIC offset: 341 BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream 1920x1080 offset: 1024 1PIXEL DATA1 3METADATA3 2METADATA2 341 90° ExifInterface SourceBufferingInputStream
  63. 158.

    BitmapFactory InputStream BufferedSource 2PIXEL DATA2 3PIXEL DATA3 4PIXEL DATA4 5PIXEL

    DATA5 6PIXEL DATA6 7PIXEL DATA7 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC 1METADATA1 MAGIC offset: 341 BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream 1920x1080 offset: 1024 1PIXEL DATA1 3METADATA3 2METADATA2 341 90° ExifInterface SourceBufferingInputStream
  64. 159.

    BitmapFactory InputStream BufferedSource 2PIXEL DATA2 3PIXEL DATA3 4PIXEL DATA4 5PIXEL

    DATA5 6PIXEL DATA6 7PIXEL DATA7 8PIXEL DATA8 9PIXEL DATA9 1METADATA1 MAGIC offset: 341 BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream 1920x1080 offset: 1024 1PIXEL DATA1 3METADATA3 2METADATA2 341 90° ExifInterface SourceBufferingInputStream
  65. 160.

    BitmapFactory InputStream BufferedSource 5PIXEL DATA5 6PIXEL DATA6 7PIXEL DATA7 8PIXEL

    DATA8 9PIXEL DATA9 1METADATA1 MAGIC offset: 341 BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream 1920x1080 offset: 1024 1PIXEL DATA1 3METADATA3 2METADATA2 341 90° ExifInterface SourceBufferingInputStream
  66. 161.

    BitmapFactory InputStream BufferedSource 8PIXEL DATA8 9PIXEL DATA9 1METADATA1 MAGIC offset:

    341 BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream 1920x1080 offset: 1024 1PIXEL DATA1 3METADATA3 2METADATA2 341 90° ExifInterface SourceBufferingInputStream
  67. 162.

    BitmapFactory InputStream BufferedSource 1METADATA1 MAGIC offset: 341 BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream

    1920x1080 offset: 1024 1PIXEL DATA1 3METADATA3 2METADATA2 341 90° ExifInterface SourceBufferingInputStream
  68. 163.

    BitmapFactory InputStream BufferedSource 1METADATA1 MAGIC offset: 341 BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream

    1920x1080 offset: 1024 1PIXEL DATA1 3METADATA3 2METADATA2 341 90° ExifInterface SourceBufferingInputStream
  69. 164.

    • Android P • OkHttp 2.x => 3.x
 • Okio

    integration
 • Improvements 3.x Goals
  70. 166.
  71. 167.

    Picasso fun loadImage( remoteUri: Uri, @ColorInt tintColor: Int? = null

    ) { val creator = picasso.load(remoteUri) .placeholder(avatarPlaceholder) .fit() if (transformTintColor != null) { creator.transform(TintTransformation(tintColor)) } creator.into(this) }
  72. 168.

    Picasso fun loadImage( awsAssetUri: Uri, height: Int, width: Int )

    { val creator = picasso.load(awsAssetUri) .placeholder(avatarPlaceholder) .fit() .into(this) }
  73. 169.

    Picasso fun loadImage( awsAssetUri: Uri, height: Int, width: Int )

    { val creator = picasso.load(awsAssetUri) .placeholder(avatarPlaceholder) .fit() .into(this) }
  74. 170.
  75. 183.
  76. 184.
  77. 188.
  78. 189.
  79. 190.
  80. 191.
  81. 192.
  82. 193.
  83. 194.
  84. 195.
  85. 196.
  86. 197.
  87. 198.
  88. 199.

    ?

  89. 200.
  90. 219.
  91. 224.
  92. 225.
  93. 228.

    public static Picasso with(Context context) { if (singleton == null)

    { synchronized (Picasso.class) { if (singleton == null) { singleton = new Builder(context).build(); } } } return singleton; }
  94. 229.

    public static Picasso with(Context context) { if (singleton == null)

    { synchronized (Picasso.class) { if (singleton == null) { singleton = new Builder(context).build(); } } } return singleton; }
  95. 230.

    public static void setSingletonInstance(Picasso picasso) { synchronized (Picasso.class) { if

    (singleton != null) { throw new IllegalStateException( "Singleton instance already exists."); } singleton = picasso; } }
  96. 231.

    public static void setSingletonInstance(Picasso picasso) { synchronized (Picasso.class) { if

    (singleton != null) { throw new IllegalStateException( "Singleton instance already exists."); } singleton = picasso; } }
  97. 232.

    @Module(includes = ThumborModule.class) final class ProductionPicassoModule { @Provides @Singleton static

    Picasso providePicasso( @App Context context, OkHttpClient client, Thumbor thumbor) { Picasso.RequestTransformer transformer = new PollexorRequestTransformer(thumbor); return new Picasso.Builder(context) .client(client) .requestTransformer(transformer) .listener((picasso, uri, e) -> Timber.d(e, uri.toString())); } }
  98. 233.

    @Module(includes = ThumborModule.class) final class ProductionPicassoModule { @Provides @Singleton static

    Picasso providePicasso( @App Context context, OkHttpClient client, Thumbor thumbor) { Picasso.RequestTransformer transformer = new PollexorRequestTransformer(thumbor); return new Picasso.Builder(context) .client(client) .requestTransformer(transformer) .listener((picasso, uri, e) -> Timber.d(e, uri.toString())); } }
  99. 234.
  100. 235.
  101. 236.

    public final class PicassoProvider { private static volatile Picasso instance;

    public static Picasso get() { if (instance == null) { synchronized (PicassoProvider.class) { if (instance == null) { if (PicassoContentProvider.context == null) { throw new IllegalStateException("context == null"); } instance = new Picasso.Builder(PicassoContentProvider.context).build(); } } } return instance; } }
  102. 237.

    public final class PicassoProvider { private static volatile Picasso instance;

    public static Picasso get() { if (instance == null) { synchronized (PicassoProvider.class) { if (instance == null) { if (PicassoContentProvider.context == null) { throw new IllegalStateException("context == null"); } instance = new Picasso.Builder(PicassoContentProvider.context).build(); } } } return instance; } }
  103. 238.

    public final class PicassoProvider { private static volatile Picasso instance;

    public static Picasso get() { if (instance == null) { synchronized (PicassoProvider.class) { if (instance == null) { if (PicassoContentProvider.context == null) { throw new IllegalStateException("context == null"); } instance = new Picasso.Builder(PicassoContentProvider.context).build(); } } } return instance; } }
  104. 239.

    public final class PicassoContentProvider extends ContentProvider { static Context context;

    @Override public boolean onCreate() { context = getContext(); return true; } … }
  105. 240.
  106. 241.

    • Android P • OkHttp 2.x => 3.x
 • Okio

    integration
 • Improvements 3.x Goals
  107. 246.

    abstract class RequestHandler { abstract boolean canHandleRequest(Request request); abstract void

    load(Picasso picasso, Request request, Callback callback); }X Result int networkPolicy
  108. 250.

    • Better separation of concerns: Source/Target/Load • Propagating Drawables to

    Target (animated GIFs!) • More? Let us know! Coming Soon