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

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 full-size slide

  2. 3 years later

    View full-size slide

  3. • Android P
    3.x Goals

    View full-size slide

  4. • Android P
    • Improvements
    3.x Goals

    View full-size slide

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

    View full-size slide

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

    • Okio integration
    3.x Goals

    View full-size slide

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

    • Okio integration
    3.x Goals

    View full-size slide

  8. 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 full-size slide

  9. 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 full-size slide

  10. 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 full-size slide

  11. 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 full-size slide

  12. 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 full-size slide

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

    • Okio integration
    3.x Goals

    View full-size slide

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

    View full-size slide

  15. 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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  22. p://shrek.jpg

    View full-size slide

  23. 0101011010100
    http://shrek.jpg

    View full-size slide

  24. 0101011010100
    http://shrek.jpg

    View full-size slide

  25. 01010110101001101

    View full-size slide

  26. 01010110101001101

    View full-size slide

  27. 01010110101001101

    View full-size slide

  28. 01
    01
    0110
    10100
    1 1
    0 1

    View full-size slide

  29. 01
    01
    0110
    10100
    1 1
    0 1

    View full-size slide

  30. 0x20/shrek.jpg

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  33. /**
    * 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 full-size slide

  34. 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 full-size slide

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

    View full-size slide

  36. 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 full-size slide

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

    View full-size slide

  38. @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 full-size slide

  39. @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 full-size slide

  40. @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 full-size slide

  41. @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 full-size slide

  42. @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 full-size slide

  43. @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 full-size slide

  44. @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 full-size slide

  45. /**
    * 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 full-size slide

  46. /**
    * 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 full-size slide

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

    getLifecycle().addObserver(picasso);
    }

    View full-size slide

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

    getLifecycle().addObserver(picasso);
    }

    View full-size slide

  49. @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 full-size slide

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

    View full-size slide

  51. Picasso
    Request Transformer

    View full-size slide

  52. ResourceRequestHandler
    AssetsRequestHandler
    NetworkRequestHandler
    FileRequestHandler
    Picasso
    Request Transformer

    View full-size slide

  53. Picasso
    Request Transformer
    Handler
    Request
    Resource
    AssetsRequestHandler
    NetworkRequestHandler
    FileRequestHandler

    View full-size slide

  54. Picasso
    Request Transformer
    Handler
    Request

    View full-size slide

  55. Picasso
    Request Transformer
    Request Handler
    Bitmap

    View full-size slide

  56. Bitmap
    Drawable
    Result
    Picasso
    Request Transformer
    Request Handler

    View full-size slide

  57. Picasso
    Request Transformer
    Result
    Request Handler
    Greyscale
    Circle
    Tint

    View full-size slide

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

    View full-size slide

  59. Picasso
    Request Transformer
    Result
    Target
    Request Handler
    Transformation

    View full-size slide

  60. Request Transformer
    Result
    Request Handler
    Transformation

    View full-size slide

  61. Transformer
    Result
    Transformer
    Transformer

    View full-size slide

  62. Transformer
    Transformer
    Transformer

    View full-size slide

  63. Transformer
    Transformer
    Transformer

    View full-size slide

  64. Transformer
    Transformer
    Transformer

    View full-size slide

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

    View full-size slide

  66. @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 full-size slide

  67. @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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  72. @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 full-size slide

  73. @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 full-size slide

  74. 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 full-size slide

  75. 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 full-size slide

  76. 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 full-size slide

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

    }

    View full-size slide

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





    View full-size slide

  79. 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 full-size slide

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

    View full-size slide

  81. • Android P

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

    • Okio integration
    3.x Goals

    View full-size slide

  82. Picasso
    ResourceRequestHandler
    AssetsRequestHandler
    NetworkRequestHandler
    FileRequestHandler
    ...

    View full-size slide

  83. Downloader
    Picasso
    ResourceRequestHandler
    AssetsRequestHandler
    NetworkRequestHandler
    FileRequestHandler
    ...

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  89. Picasso
    OkHttp

    View full-size slide

  90. Okio
    Picasso
    OkHttp

    View full-size slide

  91. Picasso
    OkHttp
    Retrofit
    Okio

    View full-size slide

  92. Picasso
    OkHttp
    Okio
    Retrofit
    Moshi

    View full-size slide

  93. Picasso
    OkHttp
    Okio
    Retrofit
    Moshi

    View full-size slide

  94. Picasso
    OkHttp
    Okio
    Retrofit
    Moshi Wire

    View full-size slide

  95. Picasso
    OkHttp
    Okio
    Retrofit
    Moshi Wire

    View full-size slide

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

    • Okio integration
    3.x Goals

    View full-size slide

  97. 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 full-size slide

  98. nightmare_shrek.png

    View full-size slide

  99. MAGIC
    nightmare_shrek.png

    View full-size slide

  100. METADATA
    METADATA
    METADATA
    MAGIC
    nightmare_shrek.png

    View full-size slide

  101. 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 full-size slide

  102. PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    METADATA
    METADATA
    METADATA
    MAGIC

    View full-size slide

  103. PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    METADATA
    METADATA
    METADATA
    MAGIC

    View full-size slide

  104. PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    METADATA
    METADATA
    METADATA
    MAGIC

    View full-size slide

  105. PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    METADATA
    METADATA
    METADATA
    MAGIC

    View full-size slide

  106. PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    METADATA
    METADATA
    METADATA
    MAGIC

    View full-size slide

  107. PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    METADATA
    METADATA
    METADATA
    MAGIC

    View full-size slide

  108. InputStream
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    PIXEL DATA
    METADATA
    METADATA
    METADATA
    MAGIC

    View full-size slide

  109. InputStream
    BitmapFactory
    inJustDecodeBounds=true
    MAGIC METADATA

    View full-size slide

  110. InputStream
    BitmapFactory
    inJustDecodeBounds=true
    MAGIC METADATA

    View full-size slide

  111. InputStream
    BitmapFactory
    inJustDecodeBounds=true
    MAGIC METADATA

    View full-size slide

  112. InputStream
    BitmapFactory
    inJustDecodeBounds=true
    MAGIC METADATA
    JPEG?

    View full-size slide

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

    View full-size slide

  114. InputStream
    BitmapFactory
    inJustDecodeBounds=true
    MAGIC METADATA METADAT

    View full-size slide

  115. InputStream
    BitmapFactory
    inJustDecodeBounds=true
    MAGIC
    METADATA
    METADAT

    View full-size slide

  116. InputStream
    BitmapFactory
    inJustDecodeBounds=true
    MAGIC
    METADATA
    METADAT

    View full-size slide

  117. InputStream
    BitmapFactory
    inJustDecodeBounds=true
    MAGIC METADATA

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  134. InputStream
    MAGIC METADATA

    View full-size slide

  135. InputStream
    BitmapFactory
    inJustDecodeBounds=true
    MAGIC METADATA

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  140. 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 full-size slide

  141. 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 full-size slide

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

    View full-size slide

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

    View full-size slide

  144. 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 full-size slide

  145. 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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  149. MarkableInputStream
    BitmapFactory
    inJustDecodeBounds=true

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  152. MarkableInputStream
    BitmapFactory
    inJustDecodeBounds=true

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  155. MarkableInputStream
    BitmapFactory
    inJustDecodeBounds=true

    View full-size slide

  156. MarkableInputStream
    BitmapFactory
    inJustDecodeBounds=true
    PIXEL DATA
    PIXEL DATA

    View full-size slide

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

    View full-size slide

  158. MarkableInputStream
    BitmapFactory
    inJustDecodeBounds=true
    PIXEL DATA
    PIXEL DATA

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  162. 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 full-size slide

  163. BitmapFactory MarkableInputStream InputStream
    BitmapFactory

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  167. BitmapFactory BufferedSource
    SourceBufferingInputStream

    View full-size slide

  168. BitmapFactory
    inJustDecodeBounds=true
    BufferedSource
    SourceBufferingInputStream

    View full-size slide

  169. BitmapFactory
    inJustDecodeBounds=true
    BufferedSource
    SourceBufferingInputStream
    offset: 0

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  178. 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 full-size slide

  179. 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 full-size slide

  180. 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 full-size slide

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

    View full-size slide

  182. 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 full-size slide

  183. 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 full-size slide

  184. 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 full-size slide

  185. 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 full-size slide

  186. 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 full-size slide

  187. 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 full-size slide

  188. 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 full-size slide

  189. 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 full-size slide

  190. 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 full-size slide

  191. 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 full-size slide

  192. 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 full-size slide

  193. 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 full-size slide

  194. 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 full-size slide

  195. 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 full-size slide

  196. 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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  200. BitmapFactory InputStream BufferedSource
    BitmapFactory
    inJustDecodeBounds=true
    SourceBufferingInputStream

    View full-size slide

  201. BitmapFactory
    inJustDecodeBounds=true
    BufferedSource
    SourceBufferingInputStream
    offset: 0

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  211. 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 full-size slide

  212. 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 full-size slide

  213. 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 full-size slide

  214. 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 full-size slide

  215. 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 full-size slide

  216. 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 full-size slide

  217. 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 full-size slide

  218. 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 full-size slide

  219. 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 full-size slide

  220. 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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    • Okio integration
    3.x Goals

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  234. PICASSO WILL RETURN
    3.0

    View full-size slide