Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Rinsing the Brush - Picasso 3.0 (Droidcon NYC 2018)

Rinsing the Brush - Picasso 3.0 (Droidcon NYC 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!

Co-Presented with @JakeWharton.

Video: https://youtu.be/VpNwLG3lxbo

6c8b509fe5422470d148c2c4cf2eb4b0?s=128

John Rodriguez

August 27, 2018
Tweet

Transcript

  1. Rinsing the Brush: Picasso 3.0 John Rodriguez Jake Wharton

  2. None
  3. None
  4. None
  5. None
  6. None
  7. 3 years later

  8. 3.x Goals

  9. • Android P 3.x Goals

  10. • Android P • Improvements 3.x Goals

  11. • Android P • Improvements • OkHttp 2.x => 3.x

    3.x Goals
  12. • Android P • Improvements • OkHttp 2.x => 3.x


    • Okio integration 3.x Goals
  13. • Android P • Improvements • OkHttp 2.x => 3.x


    • Okio integration 3.x Goals
  14. None
  15. None
  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); }
  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); }
  18. None
  19. Bitmap decodeStreamP(Request r, BufferedSource bs) { ImageDecoder.Source imageSource = ImageDecoder.createSource(ByteBuffer.wrap(bs.readByteArray()));

    return ImageDecoder.decodeBitmap( imageSource, (imageDecoder, imageInfo, src) -> { if (r.hasSize()) { imageDecoder.setTargetSize(r.targetWidth, r.targetHeight); } } }); }
  20. Bitmap decodeStreamP(Request r, BufferedSource bs) { ImageDecoder.Source imageSource = ImageDecoder.createSource(ByteBuffer.wrap(bs.readByteArray()));

    return ImageDecoder.decodeBitmap( imageSource, (imageDecoder, imageInfo, src) -> { if (r.hasSize()) { imageDecoder.setTargetSize(r.targetWidth, r.targetHeight); } } }); }
  21. Bitmap decodeStreamP(Request r, BufferedSource bs) { ImageDecoder.Source imageSource = ImageDecoder.createSource(ByteBuffer.wrap(bs.readByteArray()));

    return ImageDecoder.decodeBitmap( imageSource, (imageDecoder, imageInfo, src) -> { if (r.hasSize()) { imageDecoder.setTargetSize(r.targetWidth, r.targetHeight); } } }); }
  22. • Android P • Improvements • OkHttp 2.x => 3.x


    • Okio integration 3.x Goals
  23. • Android P • Improvements • OkHttp 2.x => 3.x


    • Okio integration 3.x Goals
  24. Picasso picasso.load(url) .placeholder(R.drawable.placeholder) .error(R.drawable.error) .fit() .into(view);

  25. Picasso

  26. 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) }
  27. Picasso fun loadImage( awsAssetUri: Uri, height: Int, width: Int )

    { val creator = picasso.load(awsAssetUri) .placeholder(avatarPlaceholder) .fit() .into(this) }
  28. Picasso fun loadImage( awsAssetUri: Uri, height: Int, width: Int )

    { val creator = picasso.load(awsAssetUri) .placeholder(avatarPlaceholder) .fit() .into(this) }
  29. None
  30. Picasso picasso.load(“http://shrek.jpg”) .placeholder(R.drawable.placeholder) .error(R.drawable.error) .fit() .into(view);

  31. Picasso Request “http://shrek.jpg”

  32. Picasso Request Request Transformer Request “http://shrek.jpg”

  33. Picasso Request “http://shrek.jpg” Request Transformer Request “http://bar.com/20x20/shrek.jpg”

  34. p://shrek.jpg

  35. 0101011010100 http://shrek.jpg

  36. 01010110101001101

  37. 01010110101001101

  38. 01 01 0110 10100 1 1 0 1

  39. None
  40. 0x20/shrek.jpg

  41. http://bar.com/20x20/shrek.jpg

  42. 0101011

  43. 0101011

  44. 01 010 1 1

  45. None
  46. None
  47. ?

  48. None
  49. None
  50. /** * Sets the stable key for this request to

    be used instead of the * URI or resource ID when caching. * Two requests with the same value are considered to be for the * same resource. */ public RequestCreator stableKey(String stableKey) { data.stableKey(stableKey); return this; }
  51. createNewPicasso(context, 1024, new CustomRequestHandler()); Picasso createNewPicasso( Context context, int cacheSize,

    RequestHandler requestHandler ) {e return new Picasso.Builder(context) e.withCacheSize(cacheSize) e.addRequestHandler(requestHandler) e.build(); }e
  52. createChildPicasso(builder, 1024, new CustomRequestHandler()); Picasso createChildPicasso( Picasso.Builder builder, int cacheSize,

    RequestHandler requestHandler ) { return builder .withCacheSize(cacheSize) .addRequestHandler(requestHandler) .build(); }e
  53. createChildPicasso(picasso, 1024, new CustomRequestHandler()); Picasso createChildPicasso( Picasso picasso, int cacheSize,

    RequestHandler requestHandler ) { return picasso.newBuilder() .withCacheSize(cacheSize) .addRequestHandler(requestHandler) .build(); }e builder Picasso.Builder builder, builder
  54. createChildPicasso(picasso, 1024, new CustomRequestHandler()); Picasso createChildPicasso( Picasso picasso, int cacheSize,

    RequestHandler requestHandler ) { return picasso.newBuilder() .withCacheSize(cacheSize) .addRequestHandler(requestHandler) .build(); }
  55. @Component( modules = RootModule.class ) @RootScope interface RootComponent { @Root

    Picasso picasso(); } @Module class RootModule { @Provides @RootScope @Root Picasso providePicasso(@App Context context) { return new Picasso.Builder(context) .withCacheSize(1024*1024) .build(); } }
  56. @Component( modules = RootModule.class ) @RootScope interface RootComponent { @Root

    Picasso picasso(); } @Module class RootModule { @Provides @RootScope @Root Picasso providePicasso(@App Context context) { return new Picasso.Builder(context) .withCacheSize(1024*1024) .build(); } }
  57. @Component( modules = RootModule.class ) @RootScope interface RootComponent { @Root

    Picasso picasso(); } @Module class RootModule { @Provides @RootScope @Root Picasso providePicasso(@App Context context) { return new Picasso.Builder(context) .withCacheSize(1024*1024) .build(); } }
  58. @Component( dependencies = RootComponent.class, modules = ScreenModule.class ) @ScreenScope interface

    ScreenComponent { } @Module class ScreenModule { @Provides @ScreenScope @Screen Picasso providePicasso(@Root Picasso picasso) { return picasso.newBuilder() .withCacheSize(1024) .build(); } }
  59. @Component( dependencies = RootComponent.class, modules = ScreenModule.class ) @ScreenScope interface

    ScreenComponent { } @Module class ScreenModule { @Provides @ScreenScope @Screen Picasso providePicasso(@Root Picasso picasso) { return picasso.newBuilder() .withCacheSize(1024) .build(); } }
  60. @Component( dependencies = RootComponent.class, modules = ScreenModule.class ) @ScreenScope interface

    ScreenComponent { } @Module class ScreenModule { @Provides @ScreenScope @Screen Picasso providePicasso(@Root Picasso picasso) { return picasso.newBuilder() .withCacheSize(1024) .build(); } }
  61. @Component( dependencies = RootComponent.class, modules = ScreenModule.class ) @ScreenScope interface

    ScreenComponent { } @Module class ScreenModule { @Provides @ScreenScope @Screen Picasso providePicasso(@Root Picasso picasso) { return picasso.newBuilder() .withCacheSize(1024) .build(); } }
  62. None
  63. /** * Image downloading, transformation, and caching manager. * *

    Use {@see PicassoProvider#get()} for a global singleton * instance or construct your own instance with {@link Builder}. */ public class Picasso implements LifecycleObserver { }
  64. /** * Image downloading, transformation, and caching manager. * *

    Use {@see PicassoProvider#get()} for a global singleton * instance or construct your own instance with {@link Builder}. */ public class Picasso implements LifecycleObserver { }
  65. class SampleActivity extends FragmentActivity { protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState); … getLifecycle().addObserver(picasso); }
  66. class SampleActivity extends FragmentActivity { protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState); … getLifecycle().addObserver(picasso); }
  67. @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) void cancelAll() { List<Action> actions = new ArrayList<>(targetToAction.values()); for

    (int i = 0, n = actions.size(); i < n; i++) { cancelExistingRequest(actions.get(i).getTarget()); } List<DeferredRequestCreator> deferredRequestCreators = new ArrayList<>(targetToDeferredRequestCreator.values()); for (int i = 0, n = deferredCreators.size(); i < n; i++) { deferredCreators.get(i).cancel(); } }
  68. Picasso Request “http://shrek.jpg” Request Transformer Request’ “http://bar.com/20x20/shrek.jpg”

  69. Picasso Request Transformer

  70. ResourceRequestHandler AssetsRequestHandler NetworkRequestHandler FileRequestHandler Picasso Request Transformer

  71. Picasso Request Transformer Handler Request Resource AssetsRequestHandler NetworkRequestHandler FileRequestHandler

  72. Picasso Request Transformer Handler Request

  73. Picasso Request Transformer Request Handler Bitmap

  74. Bitmap Drawable Result Picasso Request Transformer Request Handler

  75. Picasso Request Transformer Result Request Handler Greyscale Circle Tint

  76. Greyscale Circle Tint Picasso Request Transformer Result Request Handler Transformation

  77. Picasso Request Transformer Result Target Request Handler Transformation

  78. Request Transformer Result Request Handler Transformation

  79. Transformer Result Transformer Transformer

  80. Transformer Transformer Transformer

  81. Transformer Transformer Transformer

  82. Transformer Transformer Transformer

  83. custom interceptors Retry Bridge Cache Connect Call Server square/okhttp

  84. None
  85. @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Picasso.with(this) .load("http://example.com/logo.png")

    .into(imageView); }
  86. @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Picasso.with(this) .load("http://example.com/logo.png")

    .into(imageView); }
  87. public static Picasso with(Context context) { if (singleton == null)

    { synchronized (Picasso.class) { if (singleton == null) { singleton = new Builder(context).build(); } } } return singleton; }
  88. public static Picasso with(Context context) { if (singleton == null)

    { synchronized (Picasso.class) { if (singleton == null) { singleton = new Builder(context).build(); } } } return singleton; }
  89. public static void setSingletonInstance(Picasso picasso) { synchronized (Picasso.class) { if

    (singleton != null) { throw new IllegalStateException( "Singleton instance already exists."); } singleton = picasso; } }
  90. public static void setSingletonInstance(Picasso picasso) { synchronized (Picasso.class) { if

    (singleton != null) { throw new IllegalStateException( "Singleton instance already exists."); } singleton = picasso; } }
  91. @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())); } }
  92. @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())); } }
  93. None
  94. None
  95. 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; } }
  96. 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; } }
  97. 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; } }
  98. public final class PicassoContentProvider extends ContentProvider { static Context context;

    @Override public boolean onCreate() { context = getContext(); return true; } … }
  99. None
  100. <activity android:name=".Issue1955" android:process="not-the-main-process" > <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter>

    </activity>
  101. None
  102. interface ImageDecoder { class Image { @Nullable Bitmap bitmap; @Nullable

    Drawable drawable; int exifOrientation; } boolean canHandleSource(BufferedSource source); Image decodeImage(BufferedSource source, Request request) throws IOException; }
  103. class ImageDecoderFactory { List<ImageDecoder> decoders; ImageDecoder getImageDecoderForSource(BufferedSource source) { for

    (ImageDecoder decoder : decoders) { if (decoder.canHandleSource(source)) { return decoder; } } return null; } }
  104. Picasso

  105. Picasso?

  106. • Android P
 • Improvements • OkHttp 2.x => 3.x


    • Okio integration 3.x Goals
  107. Picasso

  108. Picasso ResourceRequestHandler AssetsRequestHandler NetworkRequestHandler FileRequestHandler ...

  109. Downloader Picasso ResourceRequestHandler AssetsRequestHandler NetworkRequestHandler FileRequestHandler ...

  110. OkHttp 2.x HttpURLConnection Downloader Picasso ResourceRequestHandler AssetsRequestHandler NetworkRequestHandler FileRequestHandler ...

  111. OkHttp 2.x HttpURLConnection OkHttp 3.x Downloader Picasso ResourceRequestHandler AssetsRequestHandler NetworkRequestHandler

    FileRequestHandler ...
  112. OkHttp 3.x HttpURLConnection OkHttp 2.x Downloader Picasso ResourceRequestHandler AssetsRequestHandler NetworkRequestHandler

    FileRequestHandler ...
  113. OkHttp 3.x Picasso ResourceRequestHandler AssetsRequestHandler NetworkRequestHandler FileRequestHandler ...

  114. Picasso ResourceRequestHandler AssetsRequestHandler NetworkRequestHandler FileRequestHandler ... OkHttp 3.x

  115. Picasso ResourceRequestHandler AssetsRequestHandler NetworkRequestHandler FileRequestHandler ... Call.Factory (OkHttp 3.x)

  116. Picasso OkHttp

  117. Okio Picasso OkHttp

  118. Picasso OkHttp Retrofit Okio

  119. Picasso OkHttp Okio Retrofit Moshi

  120. Picasso OkHttp Okio Retrofit Moshi

  121. Picasso OkHttp Okio Retrofit Moshi Wire

  122. Picasso OkHttp Okio Retrofit Moshi Wire

  123. • Android P • Improvements • OkHttp 2.x => 3.x


    • Okio integration 3.x Goals
  124. 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)
  125. 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
  126. PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA

    PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA METADATA METADATA METADATA MAGIC
  127. PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA

    PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA METADATA METADATA METADATA MAGIC
  128. PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA

    PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA METADATA METADATA METADATA MAGIC
  129. PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA

    PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA METADATA METADATA METADATA MAGIC
  130. InputStream PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL

    DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA METADATA METADATA METADATA MAGIC
  131. InputStream BitmapFactory inJustDecodeBounds=true MAGIC METADATA

  132. InputStream BitmapFactory inJustDecodeBounds=true MAGIC METADATA JPEG?

  133. InputStream BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADAT JPEG?

  134. InputStream BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADAT

  135. InputStream BitmapFactory inJustDecodeBounds=true MAGIC METADATA

  136. BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA METADATA PIXEL DATA JPEG?

  137. BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA METADATA PIXEL DATA JPEG?

  138. BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA METADATA PIXEL DATA PNG?

  139. BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA METADATA PIXEL DATA PNG?

  140. BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA METADATA PIXEL DATA PNG!

  141. BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA METADATA PIXEL DATA PNG size?

  142. BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA METADATA PIXEL DATA PNG size?

  143. BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA METADATA PIXEL DATA PNG 1920x1080!

  144. BitmapFactory inJustDecodeBounds=true MAGIC METADATA 2METADATA2 1METADATA1 PIXEL DATA PNG 1920x1080!

  145. BitmapFactory inJustDecodeBounds=true MAGIC METADATA 2METADATA2 1METADATA1 PIXEL DATA PNG 1920x1080

  146. BitmapFactory inJustDecodeBounds=true MAGIC METADATA 2METADATA2 1METADATA1 PIXEL DATA 1920x1080

  147. InputStream BitmapFactory BitmapFactory inJustDecodeBounds=true MAGIC METADATA 2METADATA2 1METADATA1 PIXEL DATA

    1920x1080 PIXEL DAT
  148. InputStream BitmapFactory inJustDecodeBounds=true BitmapFactory PIXEL DATA MAGIC METADATA 2METADATA2 1METADATA1

    PIXEL DATA 1920x1080
  149. InputStream BitmapFactory inJustDecodeBounds=true BitmapFactory PIXEL DATA MAGIC METADATA 2METADATA2 1METADATA1

    PIXEL DATA 1920x1080
  150. InputStream BitmapFactory inJustDecodeBounds=true BitmapFactory PIXEL DATA MAGIC METADATA 2METADATA2 1METADATA1

    PIXEL DATA 1920x1080
  151. InputStream BitmapFactory inJustDecodeBounds=true BitmapFactory PIXEL DATA MAGIC METADATA METADATA METADATA

    PIXEL DATA 1920x1080
  152. InputStream BitmapFactory inJustDecodeBounds=true MAGIC METADATA

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

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

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

    METADATA METADATA METADATA PIXEL DATA 1920x1080
  156. BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA METADATA PIXEL DATA MarkableInputStream MAGIC

    METADATA METADATA METADATA PIXEL DATA 1920x1080
  157. BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA METADATA PIXEL DATA MarkableInputStream MAGIC

    METADATA METADATA METADATA PIXEL DATA 1920x1080 BitmapFactory MAGIC METADATA METADATA METADATA PIXEL DATA
  158. BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA METADATA PIXEL DATA MarkableInputStream MAGIC

    METADATA METADATA METADATA PIXEL DATA 1920x1080 MAGIC METADATA METADATA METADATA PIXEL DATA BitmapFactory
  159. BitmapFactory inJustDecodeBounds=true MarkableInputStream MAGIC METADATA METADATA METADATA PIXEL DATA 1920x1080

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

    METADATA METADATA METADATA PIXEL DATA 1920x1080 BitmapFactory
  161. PIXEL DATA PIXEL DATA PIXEL DATA BitmapFactory inJustDecodeBounds=true MarkableInputStream MAGIC

    METADATA METADATA METADATA PIXEL DATA 1920x1080 BitmapFactory PIXEL DATA PIXEL DATA PIXEL DATA
  162. PIXEL DATA PIXEL DATA PIXEL DATA BitmapFactory inJustDecodeBounds=true MarkableInputStream MAGIC

    METADATA METADATA METADATA PIXEL DATA 1920x1080 BitmapFactory PIXEL DATA PIXEL DATA PIXEL DATA
  163. BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA METADATA PIXEL DATA MarkableInputStream MAGIC

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

    METADATA METADATA METADATA PIXEL DATA
  165. MarkableInputStream BitmapFactory inJustDecodeBounds=true

  166. PIXEL DATA PIXEL DATA PIXEL DATA MarkableInputStream BitmapFactory inJustDecodeBounds=true

  167. PIXEL DATA PIXEL DATA PIXEL DATA MarkableInputStream BitmapFactory inJustDecodeBounds=true PIXEL

    DATA PIXEL DATA PIXEL DATA
  168. PIXEL DATA PIXEL DATA PIXEL DATA MarkableInputStream BitmapFactory inJustDecodeBounds=true PIXEL

    DATA PIXEL DATA PIXEL DATA
  169. MarkableInputStream BitmapFactory inJustDecodeBounds=true

  170. MarkableInputStream BitmapFactory inJustDecodeBounds=true PIXEL DATA PIXEL DATA PIXEL DATA

  171. MarkableInputStream BitmapFactory inJustDecodeBounds=true PIXEL DATA PIXEL DATA PIXEL DATA PIXEL

    DATA PIXEL DATA PIXEL DATA
  172. MarkableInputStream BitmapFactory inJustDecodeBounds=true PIXEL DATA PIXEL DATA PIXEL DATA PIXEL

    DATA PIXEL DATA PIXEL DATA
  173. MarkableInputStream BitmapFactory inJustDecodeBounds=true

  174. MarkableInputStream BitmapFactory inJustDecodeBounds=true PIXEL DATA PIXEL DATA

  175. MarkableInputStream BitmapFactory inJustDecodeBounds=true PIXEL DATA PIXEL DATA PIXEL DATA PIXEL

    DATA
  176. MarkableInputStream BitmapFactory inJustDecodeBounds=true PIXEL DATA PIXEL DATA PIXEL DATA PIXEL

    DATA
  177. MarkableInputStream BitmapFactory inJustDecodeBounds=true ??? PIXEL DATA PIXEL DATA

  178. MarkableInputStream BitmapFactory inJustDecodeBounds=true ??? BitmapFactory PIXEL DATA PIXEL DATA

  179. 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)
  180. BitmapFactory MarkableInputStream InputStream BitmapFactory

  181. BitmapFactory MarkableInputStream InputStream Picasso 2.x BitmapFactory BufferedSource Picasso 3.x

  182. BitmapFactory MarkableInputStream InputStream Picasso 2.x BitmapFactory BufferedSource Picasso 3.x SourceBufferingInputStream

  183. BitmapFactory BufferedSource SourceBufferingInputStream

  184. BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream offset: 0

  185. BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC

    offset: 0
  186. BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC

    offset: 0 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC
  187. BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC

    offset: 0 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC 1024
  188. BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC

    offset: 1024 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC 0
  189. BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC

    offset: 1024 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC
  190. BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC

    offset: 1024 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC
  191. BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC

    offset: 1024 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC
  192. BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC

    offset: 1024
  193. BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 2PIXEL DATA2 3PIXEL DATA3 4PIXEL DATA4

    1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC offset: 1024
  194. 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
  195. 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
  196. 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
  197. 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
  198. BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 2PIXEL DATA2 3PIXEL DATA3 4PIXEL DATA4

    1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC offset: 2048
  199. 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
  200. 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
  201. 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
  202. 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
  203. 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
  204. 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
  205. 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
  206. 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 8PIXEL DATA8 9PIXEL DATA9 offset:x3072
  207. 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
  208. 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
  209. 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
  210. 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 ???
  211. 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
  212. 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
  213. 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
  214. 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
  215. BitmapFactory InputStream BufferedSource 2PIXEL DATA2 3PIXEL DATA3 4PIXEL DATA4 5PIXEL

    DATA5 6PIXEL DATA6 7PIXEL DATA7 8PIXEL DATA8 9PIXEL DATA9 BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream
  216. BitmapFactory InputStream BufferedSource 5PIXEL DATA5 6PIXEL DATA6 7PIXEL DATA7 8PIXEL

    DATA8 9PIXEL DATA9 BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream
  217. BitmapFactory InputStream BufferedSource 8PIXEL DATA8 9PIXEL DATA9 BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream

  218. BitmapFactory InputStream BufferedSource BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream

  219. BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream offset: 0

  220. BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream offset: 0

  221. BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 1METADATA1 MAGIC offset: 0

  222. BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 1METADATA1 MAGIC offset: 0 1METADATA1 MAGIC

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

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

    1920x1080
  225. ExifInterface BufferedSource SourceBufferingInputStream 1METADATA1 MAGIC 1METADATA1 MAGIC offset: 341 BitmapFactory

    inJustDecodeBounds=true SourceBufferingInputStream 1920x1080 offset: 0
  226. ExifInterface BufferedSource SourceBufferingInputStream 1METADATA1 MAGIC 1METADATA1 MAGIC offset: 341 BitmapFactory

    inJustDecodeBounds=true SourceBufferingInputStream 1920x1080 offset: 0 1METADATA1 MAGIC
  227. ExifInterface BufferedSource SourceBufferingInputStream 1METADATA1 MAGIC 1METADATA1 MAGIC offset: 341 BitmapFactory

    inJustDecodeBounds=true SourceBufferingInputStream 1920x1080 offset: 341 1METADATA1 MAGIC
  228. ExifInterface BufferedSource SourceBufferingInputStream 1METADATA1 MAGIC 1METADATA1 MAGIC offset: 341 BitmapFactory

    inJustDecodeBounds=true SourceBufferingInputStream 1920x1080 offset: 341 1METADATA1 MAGIC
  229. ExifInterface BufferedSource SourceBufferingInputStream 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC 1METADATA1

    MAGIC offset: 341 BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream 1920x1080 offset: 341
  230. ExifInterface BufferedSource SourceBufferingInputStream 1PIXEL DATA1 3METADATA3 2METADATA2 1METADATA1 MAGIC 1METADATA1

    MAGIC offset: 341 BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream 1920x1080 offset: 341 1PIXEL DATA1 3METADATA3 2METADATA2
  231. 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
  232. 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°
  233. 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
  234. 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
  235. 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
  236. 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
  237. 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
  238. 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
  239. BitmapFactory InputStream BufferedSource 1METADATA1 MAGIC offset: 341 BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream

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

    1920x1080 offset: 1024 1PIXEL DATA1 3METADATA3 2METADATA2 341 90° ExifInterface SourceBufferingInputStream
  241. • Android P • Improvements • OkHttp 2.x => 3.x


    • Okio integration 3.x Goals
  242. Picasso.with(context)X .load(url) .placeholder(R.drawable.placeholder) .error(R.drawable.error) .fit() .into(view);

  243. PicassoProvider.get()X .load(url) .placeholder(R.drawable.placeholder) .error(R.drawable.error) .fit() .into(view); with context

  244. picasso.load(url) .placeholder(R.drawable.placeholder) .error(R.drawable.error) .fit() .into(view);

  245. abstract class RequestHandler { abstract boolean canHandleRequest(Request request); abstract Result

    load(Request request, int networkPolicy); }X
  246. abstract class RequestHandler { abstract boolean canHandleRequest(Request request); abstract void

    load(Picasso picasso, Request request, Callback callback); }X Result int networkPolicy
  247. • Better separation of concerns: Image/Target/RenderCall • Propagating Drawables to

    Target (animated GIFs!) • Improved pipelining • More? Let us know! Coming Soon
  248. Rinsing the Brush: Picasso 3.0 @jrodbx @JakeWharton

  249. PICASSO WILL RETURN 3.0