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 how Picasso works
* Explore ImageDecoder, BitmapFactory's successor in Android P
* 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!

Video: https://youtu.be/VpNwLG3lxbo

Jake Wharton
PRO

August 27, 2018
Tweet

More Decks by Jake Wharton

Other Decks in Programming

Transcript

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

    View Slide

  2. View Slide

  3. View Slide

  4. View Slide

  5. View Slide

  6. View Slide

  7. 3 years later

    View Slide

  8. 3.x Goals

    View Slide

  9. • Android P
    3.x Goals

    View Slide

  10. • Android P
    • Improvements
    3.x Goals

    View Slide

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

    View Slide

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

    • Okio integration
    3.x Goals

    View Slide

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

    • Okio integration
    3.x Goals

    View Slide

  14. View Slide

  15. View Slide

  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);
    }

    View Slide

  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);
    }

    View Slide

  18. View Slide

  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);
    }
    }
    });
    }

    View Slide

  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);
    }
    }
    });
    }

    View Slide

  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);
    }
    }
    });
    }

    View Slide

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

    • Okio integration
    3.x Goals

    View Slide

  23. Picasso

    View Slide

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

    View Slide

  25. Picasso

    View Slide

  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)
    }

    View Slide

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

    View Slide

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

    View Slide

  29. View Slide

  30. Picasso
    picasso.load(“http://shrek.jpg”)
    .placeholder(R.drawable.placeholder)
    .error(R.drawable.error)
    .fit()
    .into(view);

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  34. p://shrek.jpg

    View Slide

  35. 0101011010100
    http://shrek.jpg

    View Slide

  36. 0101011010100
    http://shrek.jpg

    View Slide

  37. 01010110101001101

    View Slide

  38. 01010110101001101

    View Slide

  39. 01010110101001101

    View Slide

  40. 01
    01
    0110
    10100
    1 1
    0 1

    View Slide

  41. 01
    01
    0110
    10100
    1 1
    0 1

    View Slide

  42. View Slide

  43. View Slide

  44. 0x20/shrek.jpg

    View Slide

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

    View Slide

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

    View Slide

  47. 0101011

    View Slide

  48. 0101011

    View Slide

  49. 0101011

    View Slide

  50. 0101011

    View Slide

  51. 0101011

    View Slide

  52. 01
    010
    1 1

    View Slide

  53. 01
    010
    1 1

    View Slide

  54. 01
    010
    1 1

    View Slide

  55. View Slide

  56. View Slide

  57. View Slide

  58. View Slide

  59. ?

    View Slide

  60. View Slide

  61. View Slide

  62. View Slide

  63. /**
    * 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;
    }

    View Slide

  64. 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

    View Slide

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

    View Slide

  66. 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

    View Slide

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

    View Slide

  68. @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();
    }
    }

    View Slide

  69. @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();
    }
    }

    View Slide

  70. @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();
    }
    }

    View Slide

  71. @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();
    }
    }

    View Slide

  72. @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();
    }
    }

    View Slide

  73. @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();
    }
    }

    View Slide

  74. @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();
    }
    }

    View Slide

  75. View Slide

  76. View Slide

  77. /**
    * 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 {
    }

    View Slide

  78. /**
    * 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 {
    }

    View Slide

  79. class SampleActivity extends FragmentActivity {
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    getLifecycle().addObserver(picasso);
    }

    View Slide

  80. class SampleActivity extends FragmentActivity {
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    getLifecycle().addObserver(picasso);
    }

    View Slide

  81. @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    void cancelAll() {
    List actions = new ArrayList<>(targetToAction.values());
    for (int i = 0, n = actions.size(); i < n; i++) {
    cancelExistingRequest(actions.get(i).getTarget());
    }
    List deferredRequestCreators =
    new ArrayList<>(targetToDeferredRequestCreator.values());
    for (int i = 0, n = deferredCreators.size(); i < n; i++) {
    deferredCreators.get(i).cancel();
    }
    }

    View Slide

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

    View Slide

  83. Picasso
    Request Transformer

    View Slide

  84. ResourceRequestHandler
    AssetsRequestHandler
    NetworkRequestHandler
    FileRequestHandler
    Picasso
    Request Transformer

    View Slide

  85. Picasso
    Request Transformer
    Handler
    Request
    Resource
    AssetsRequestHandler
    NetworkRequestHandler
    FileRequestHandler

    View Slide

  86. Picasso
    Request Transformer
    Handler
    Request

    View Slide

  87. Picasso
    Request Transformer
    Request Handler
    Bitmap

    View Slide

  88. Bitmap
    Drawable
    Result
    Picasso
    Request Transformer
    Request Handler

    View Slide

  89. Picasso
    Request Transformer
    Result
    Request Handler
    Greyscale
    Circle
    Tint

    View Slide

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

    View Slide

  91. Picasso
    Request Transformer
    Result
    Target
    Request Handler
    Transformation

    View Slide

  92. Request Transformer
    Result
    Request Handler
    Transformation

    View Slide

  93. Transformer
    Result
    Transformer
    Transformer

    View Slide

  94. Transformer
    Transformer
    Transformer

    View Slide

  95. Transformer
    Transformer
    Transformer

    View Slide

  96. Transformer
    Transformer
    Transformer

    View Slide

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

    View Slide

  98. View Slide

  99. View Slide

  100. @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);
    }

    View Slide

  101. @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);
    }

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  106. @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()));
    }
    }

    View Slide

  107. @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()));
    }
    }

    View Slide

  108. View Slide

  109. View Slide

  110. 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;
    }
    }

    View Slide

  111. 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;
    }
    }

    View Slide

  112. 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;
    }
    }

    View Slide

  113. public final class PicassoContentProvider extends ContentProvider {
    static Context context;
    @Override public boolean onCreate() {
    context = getContext();
    return true;
    }

    }

    View Slide

  114. View Slide

  115. android:name=".Issue1955"
    android:process="not-the-main-process"
    >





    View Slide

  116. View Slide

  117. View Slide

  118. interface ImageDecoder {
    class Image {
    @Nullable Bitmap bitmap;
    @Nullable Drawable drawable;
    int exifOrientation;
    }
    boolean canHandleSource(BufferedSource source);
    Image decodeImage(BufferedSource source, Request request)
    throws IOException;
    }

    View Slide

  119. class ImageDecoderFactory {
    List decoders;
    ImageDecoder getImageDecoderForSource(BufferedSource source) {
    for (ImageDecoder decoder : decoders) {
    if (decoder.canHandleSource(source)) {
    return decoder;
    }
    }
    return null;
    }
    }

    View Slide

  120. Picasso

    View Slide

  121. Picasso?

    View Slide

  122. • Android P

    • Improvements
    • OkHttp 2.x => 3.x

    • Okio integration
    3.x Goals

    View Slide

  123. Picasso

    View Slide

  124. Picasso
    ResourceRequestHandler
    AssetsRequestHandler
    NetworkRequestHandler
    FileRequestHandler
    ...

    View Slide

  125. Downloader
    Picasso
    ResourceRequestHandler
    AssetsRequestHandler
    NetworkRequestHandler
    FileRequestHandler
    ...

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  131. Picasso
    OkHttp

    View Slide

  132. Okio
    Picasso
    OkHttp

    View Slide

  133. Picasso
    OkHttp
    Retrofit
    Okio

    View Slide

  134. Picasso
    OkHttp
    Okio
    Retrofit
    Moshi

    View Slide

  135. Picasso
    OkHttp
    Okio
    Retrofit
    Moshi

    View Slide

  136. Picasso
    OkHttp
    Okio
    Retrofit
    Moshi Wire

    View Slide

  137. Picasso
    OkHttp
    Okio
    Retrofit
    Moshi Wire

    View Slide

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

    • Okio integration
    3.x Goals

    View Slide

  139. 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)

    View Slide

  140. nightmare_shrek.png

    View Slide

  141. MAGIC
    nightmare_shrek.png

    View Slide

  142. METADATA
    METADATA
    METADATA
    MAGIC
    nightmare_shrek.png

    View Slide

  143. 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

    View Slide

  144. PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    METADATA
    METADATA
    METADATA
    MAGIC

    View Slide

  145. PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    METADATA
    METADATA
    METADATA
    MAGIC

    View Slide

  146. PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    METADATA
    METADATA
    METADATA
    MAGIC

    View Slide

  147. PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    METADATA
    METADATA
    METADATA
    MAGIC

    View Slide

  148. PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    METADATA
    METADATA
    METADATA
    MAGIC

    View Slide

  149. PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    METADATA
    METADATA
    METADATA
    MAGIC

    View Slide

  150. InputStream
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    METADATA
    METADATA
    METADATA
    MAGIC

    View Slide

  151. InputStream
    BitmapFactory
    inJustDecodeBounds=true
    MAGIC METADATA

    View Slide

  152. InputStream
    BitmapFactory
    inJustDecodeBounds=true
    MAGIC METADATA

    View Slide

  153. InputStream
    BitmapFactory
    inJustDecodeBounds=true
    MAGIC METADATA

    View Slide

  154. InputStream
    BitmapFactory
    inJustDecodeBounds=true
    MAGIC METADATA
    JPEG?

    View Slide

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

    View Slide

  156. InputStream
    BitmapFactory
    inJustDecodeBounds=true
    MAGIC METADATA METADAT

    View Slide

  157. InputStream
    BitmapFactory
    inJustDecodeBounds=true
    MAGIC
    METADATA
    METADAT

    View Slide

  158. InputStream
    BitmapFactory
    inJustDecodeBounds=true
    MAGIC
    METADATA
    METADAT

    View Slide

  159. InputStream
    BitmapFactory
    inJustDecodeBounds=true
    MAGIC METADATA

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  176. InputStream
    MAGIC METADATA

    View Slide

  177. InputStream
    BitmapFactory
    inJustDecodeBounds=true
    MAGIC METADATA

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  188. MAGIC METADATA
    METADATA
    METADATA PIXEL DATA
    MarkableInputStream
    MAGIC METADATA
    METADATA
    METADATA PIXEL DATA

    View Slide

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

    View Slide

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

    View Slide

  191. MarkableInputStream
    BitmapFactory
    inJustDecodeBounds=true

    View Slide

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

    View Slide

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

    View Slide

  194. MarkableInputStream
    BitmapFactory
    inJustDecodeBounds=true

    View Slide

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

    View Slide

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

    View Slide

  197. MarkableInputStream
    BitmapFactory
    inJustDecodeBounds=true

    View Slide

  198. MarkableInputStream
    BitmapFactory
    inJustDecodeBounds=true
    PIXEL DATA
    PIXEL DATA

    View Slide

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

    View Slide

  200. MarkableInputStream
    BitmapFactory
    inJustDecodeBounds=true
    PIXEL DATA
    PIXEL DATA

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  204. 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)

    View Slide

  205. BitmapFactory MarkableInputStream InputStream
    BitmapFactory

    View Slide

  206. BitmapFactory MarkableInputStream InputStream
    Picasso 2.x
    BitmapFactory
    Picasso 3.x

    View Slide

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

    View Slide

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

    View Slide

  209. BitmapFactory BufferedSource
    SourceBufferingInputStream

    View Slide

  210. BitmapFactory
    inJustDecodeBounds=true
    BufferedSource
    SourceBufferingInputStream

    View Slide

  211. BitmapFactory
    inJustDecodeBounds=true
    BufferedSource
    SourceBufferingInputStream
    offset: 0

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  219. BitmapFactory
    inJustDecodeBounds=true
    BufferedSource
    SourceBufferingInputStream
    2PIXEL DATA2
    3PIXEL DATA3
    4PIXEL DATA4
    1PIXEL DATA1
    3METADATA3
    2METADATA2
    1METADATA1
    MAGIC
    offset: 1024

    View Slide

  220. 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

    View Slide

  221. 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

    View Slide

  222. 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

    View Slide

  223. BitmapFactory
    inJustDecodeBounds=true
    BufferedSource
    SourceBufferingInputStream
    2PIXEL DATA2
    3PIXEL DATA3
    4PIXEL DATA4
    1PIXEL DATA1
    3METADATA3
    2METADATA2
    1METADATA1
    MAGIC
    offset: 2048

    View Slide

  224. 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

    View Slide

  225. 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

    View Slide

  226. 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

    View Slide

  227. 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

    View Slide

  228. 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

    View Slide

  229. 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

    View Slide

  230. 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

    View Slide

  231. 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

    View Slide

  232. 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

    View Slide

  233. 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

    View Slide

  234. 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
    ???

    View Slide

  235. 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

    View Slide

  236. 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

    View Slide

  237. 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

    View Slide

  238. 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

    View Slide

  239. BitmapFactory InputStream BufferedSource
    2PIXEL DATA2
    3PIXEL DATA3
    4PIXEL DATA4
    5PIXEL DATA5
    6PIXEL DATA6
    7PIXEL DATA7
    8PIXEL DATA8
    9PIXEL DATA9
    BitmapFactory
    inJustDecodeBounds=true
    SourceBufferingInputStream

    View Slide

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

    View Slide

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

    View Slide

  242. BitmapFactory InputStream BufferedSource
    BitmapFactory
    inJustDecodeBounds=true
    SourceBufferingInputStream

    View Slide

  243. BitmapFactory
    inJustDecodeBounds=true
    BufferedSource
    SourceBufferingInputStream
    offset: 0

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  253. 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

    View Slide

  254. 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

    View Slide

  255. 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°

    View Slide

  256. 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

    View Slide

  257. 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

    View Slide

  258. 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

    View Slide

  259. 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

    View Slide

  260. 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

    View Slide

  261. 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

    View Slide

  262. 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

    View Slide

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

    View Slide

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

    View Slide

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

    • Okio integration
    3.x Goals

    View Slide

  266. Picasso.with(context)X
    .load(url)
    .placeholder(R.drawable.placeholder)
    .error(R.drawable.error)
    .fit()
    .into(view);

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  270. abstract class RequestHandler {
    abstract boolean canHandleRequest(Request request);
    abstract void load(Picasso picasso, Request request, Callback callback);
    }X
    Result int networkPolicy

    View Slide

  271. • Better separation of concerns: Image/Target/RenderCall
    Coming Soon

    View Slide

  272. • Better separation of concerns: Image/Target/RenderCall
    • Propagating Drawables to Target (animated GIFs!)
    Coming Soon

    View Slide

  273. • Better separation of concerns: Image/Target/RenderCall
    • Propagating Drawables to Target (animated GIFs!)
    • Improved pipelining
    Coming Soon

    View Slide

  274. • Better separation of concerns: Image/Target/RenderCall
    • Propagating Drawables to Target (animated GIFs!)
    • Improved pipelining
    • More? Let us know!
    Coming Soon

    View Slide

  275. Rinsing the Brush:
    Picasso 3.0
    @jrodbx @JakeWharton

    View Slide

  276. PICASSO WILL RETURN
    3.0

    View Slide