Rinsing the Brush: Picasso 3.0 John Rodriguez Jake Wharton

3 years later

3.x Goals

• Android P 3.x Goals

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

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

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

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

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

}

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

}

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

return ImageDecoder. decodeBitmap ( imageSource ,
new OnHeaderDecodedListener() {

void onHeaderDecoded (ImageDecoder d , ImageInfo info , Source src) {

if ( r .hasSize()) {

d.setTargetSize( r . targetWidth , r . targetHeight ) ;

} } }) ; }

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

return ImageDecoder. decodeBitmap ( imageSource ,
new OnHeaderDecodedListener() {

void onHeaderDecoded (ImageDecoder d , ImageInfo info , Source src) {

if ( r .hasSize()) {

d.setTargetSize( r . targetWidth , r . targetHeight ) ;

} } }) ; }

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

return ImageDecoder. decodeBitmap ( imageSource ,
new OnHeaderDecodedListener() {

void onHeaderDecoded (ImageDecoder d , ImageInfo info , Source src) {

if ( r .hasSize()) {

d.setTargetSize( r . targetWidth , r . targetHeight ) ;

} } }) ; }

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

Picasso

Picasso ResourceRequestHandler AssetsRequestHandler NetworkRequestHandler FileRequestHandler ...

Downloader Picasso NetworkRequestHandler ResourceRequestHandler AssetsRequestHandler FileRequestHandler ...

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

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

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

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

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

Picasso OkHttp

Okio Picasso OkHttp

Picasso OkHttp Retrofit Okio

Picasso OkHttp Okio Retrofit Moshi

Picasso OkHttp Okio Retrofit Moshi

Picasso OkHttp Okio Retrofit Moshi Wire

Okio

Picasso OkHttp Retrofit Moshi Wire

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

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 )

nightmare_shrek.png

MAGIC nightmare_shrek.png

METADATA METADATA METADATA MAGIC nightmare_shrek.png

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

PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA METADATA METADATA METADATA MAGIC

PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA METADATA METADATA METADATA MAGIC

PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA METADATA METADATA METADATA MAGIC

PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA METADATA METADATA METADATA MAGIC

PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA METADATA METADATA METADATA MAGIC

PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA METADATA METADATA METADATA MAGIC

InputStream PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA METADATA METADATA METADATA MAGIC

InputStream BitmapFactory

inJustDecodeBounds=true MAGIC METADATA

InputStream BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA

InputStream BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA JPEG?

InputStream BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA JPEG?

InputStream BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA JPEG?

InputStream BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA

InputStream BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA

InputStream BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA

InputStream BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA

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

InputStream BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA METADATA PIXEL DATA PIXEL DATA JPEG?

InputStream BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA METADATA PIXEL DATA JPEG? PIXEL DATA

InputStream BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA METADATA PIXEL DATA JPEG? PIXEL DATA

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

InputStream BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA METADATA PIXEL DATA PNG? PIXEL DATA

InputStream BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA METADATA PIXEL DATA PNG? PIXEL DATA

InputStream BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA METADATA PIXEL DATA PNG! PIXEL DATA

InputStream BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA METADATA PIXEL DATA PNG PIXEL DATA

InputStream BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA METADATA PIXEL DATA PNG size? PIXEL DATA

InputStream BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA METADATA PIXEL DATA PNG size? PIXEL DATA

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

InputStream BitmapFactory inJustDecodeBounds=true MAGIC METADATA 2 METADATA 2 1 METADATA 1 PIXEL DATA PNG 1920x1080 PIXEL DATA

InputStream 1920x1080 PIXEL DATA BitmapFactory inJustDecodeBounds=true MAGIC METADATA 2 METADATA 2 1 METADATA 1 PIXEL DATA

InputStream BitmapFactory 1920x1080 PIXEL DATA BitmapFactory inJustDecodeBounds=true MAGIC METADATA 2 METADATA 2 1 METADATA 1 PIXEL DATA

InputStream BitmapFactory PIXEL DATA 1920x1080 BitmapFactory inJustDecodeBounds=true MAGIC METADATA 2 METADATA 2 1 METADATA 1 PIXEL DATA

PIXEL DATA PIXEL DATA InputStream BitmapFactory inJustDecodeBounds=true BitmapFactory MAGIC METADATA 2 METADATA 2 1 METADATA 1 1920x1080

PIXEL DATA MAGIC METADATA 2 METADATA 2 1 METADATA 1 PIXEL DATA InputStream BitmapFactory inJustDecodeBounds=true BitmapFactory 1920x1080

InputStream BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA

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

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

InputStream PIXEL DATA BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA METADATA PIXEL DATA MarkableInputStream MAGIC METADATA METADATA METADATA PIXEL DATA 1920x1080

InputStream PIXEL DATA MAGIC METADATA METADATA METADATA PIXEL DATA MarkableInputStream 1920x1080 BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA METADATA PIXEL DATA

InputStream PIXEL DATA MAGIC METADATA METADATA METADATA PIXEL DATA MarkableInputStream 1920x1080 BitmapFactory MAGIC METADATA METADATA METADATA PIXEL DATA BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA METADATA PIXEL DATA

InputStream PIXEL DATA MAGIC METADATA METADATA METADATA PIXEL DATA MarkableInputStream 1920x1080 MAGIC METADATA METADATA METADATA PIXEL DATA BitmapFactory BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA METADATA PIXEL DATA

InputStream PIXEL DATA MarkableInputStream 1920x1080 BitmapFactory METADATA METADATA PIXEL DATA BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA METADATA PIXEL DATA

InputStream PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA MarkableInputStream 1920x1080 BitmapFactory METADATA METADATA PIXEL DATA BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA METADATA PIXEL DATA

InputStream PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA MarkableInputStream 1920x1080 BitmapFactory METADATA METADATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA BitmapFactory inJustDecodeBounds=true MAGIC METADATA METADATA METADATA PIXEL DATA

InputStream PIXEL DATA MAGIC METADATA METADATA METADATA PIXEL DATA MarkableInputStream MAGIC METADATA METADATA METADATA PIXEL DATA

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

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

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

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

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

InputStream PIXEL DATA MarkableInputStream BitmapFactory inJustDecodeBounds=true PIXEL DATA PIXEL DATA PIXEL DATA

InputStream MarkableInputStream BitmapFactory inJustDecodeBounds=true PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA

InputStream MarkableInputStream BitmapFactory inJustDecodeBounds=true PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA

InputStream MarkableInputStream BitmapFactory inJustDecodeBounds=true PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA

InputStream MarkableInputStream BitmapFactory inJustDecodeBounds=true PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA

InputStream MarkableInputStream BitmapFactory inJustDecodeBounds=true PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA

InputStream MarkableInputStream BitmapFactory inJustDecodeBounds=true PIXEL DATA PIXEL DATA PIXEL DATA PIXEL DATA

InputStream MarkableInputStream BitmapFactory inJustDecodeBounds=true PIXEL DATA PIXEL DATA ??? PIXEL DATA PIXEL DATA

InputStream MarkableInputStream ??? PIXEL DATA PIXEL DATA BitmapFactory inJustDecodeBounds=true

InputStream MarkableInputStream ??? BitmapFactory PIXEL DATA PIXEL DATA BitmapFactory inJustDecodeBounds=true

InputStream MarkableInputStream ??? 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 ) BitmapFactory inJustDecodeBounds=true

BitmapFactory MarkableInputStream InputStream BitmapFactory

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

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

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

BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream

BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream offset: 0

BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC offset: 0

BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC offset: 0 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC 1024

BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC offset: 1024 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC 0

BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC offset: 1024 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC

BufferedSource 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream

offset: 1024 1PIXEL DATA 1 3METADATA 3 2METADATA 2 1METADATA 1 MAGIC

BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC offset: 1024 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC

BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC offset: 1024

BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 2 PIXEL DATA 2 3 PIXEL DATA 3 4 PIXEL DATA 4 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC offset: 1024

BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 2 PIXEL DATA 2 3 PIXEL DATA 3 4 PIXEL DATA 4 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC offset: 1024 2 PIXEL DATA 2 3 PIXEL DATA 3 4 PIXEL DATA 4 2048

BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 2 PIXEL DATA 2 3 PIXEL DATA 3 4 PIXEL DATA 4 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC offset: 2048 2 PIXEL DATA 2 3 PIXEL DATA 3 4 PIXEL DATA 4 1024

BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 2 PIXEL DATA 2 3 PIXEL DATA 3 4 PIXEL DATA 4 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC offset: 2048 2 PIXEL DATA 2 3 PIXEL DATA 3 4 PIXEL DATA 4

BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 2 PIXEL DATA 2 3 PIXEL DATA 3 4 PIXEL DATA 4 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC offset: 2048

BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 2 PIXEL DATA 2 3 PIXEL DATA 3 4 PIXEL DATA 4 5 PIXEL DATA 5 6 PIXEL DATA 6 7 PIXEL DATA 7 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC offset: 2048

BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 2 PIXEL DATA 2 3 PIXEL DATA 3 4 PIXEL DATA 4 5 PIXEL DATA 5 6 PIXEL DATA 6 7 PIXEL DATA 7 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC offset: 2048 5 PIXEL DATA 5 6 PIXEL DATA 6 7 PIXEL DATA 7 3072

BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 2 PIXEL DATA 2 3 PIXEL DATA 3 4 PIXEL DATA 4 5 PIXEL DATA 5 6 PIXEL DATA 6 7 PIXEL DATA 7 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC offset: 3072 5 PIXEL DATA 5 6 PIXEL DATA 6 7 PIXEL DATA 7 2048

BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 2 PIXEL DATA 2 3 PIXEL DATA 3 4 PIXEL DATA 4 5 PIXEL DATA 5 6 PIXEL DATA 6 7 PIXEL DATA 7 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC offset: 3072 5 PIXEL DATA 5 6 PIXEL DATA 6 7 PIXEL DATA 7

BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 2 PIXEL DATA 2 3 PIXEL DATA 3 4 PIXEL DATA 4 5 PIXEL DATA 5 6 PIXEL DATA 6 7 PIXEL DATA 7 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC offset: 3072

BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 2 PIXEL DATA 2 3 PIXEL DATA 3 4 PIXEL DATA 4 5 PIXEL DATA 5 6 PIXEL DATA 6 7 PIXEL DATA 7 8 PIXEL DATA 8 9 PIXEL DATA 9 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC offset: 3072

BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 2 PIXEL DATA 2 3 PIXEL DATA 3 4 PIXEL DATA 4 5 PIXEL DATA 5 6 PIXEL DATA 6 7 PIXEL DATA 7 8 PIXEL DATA 8 9 PIXEL DATA 9 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC offset: x 3072 8 PIXEL DATA 8 9 PIXEL DATA 9 3754

BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 2 PIXEL DATA 2 3 PIXEL DATA 3 4 PIXEL DATA 4 5 PIXEL DATA 5 6 PIXEL DATA 6 7 PIXEL DATA 7 8 PIXEL DATA 8 9 PIXEL DATA 9 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC offset: 3754 8 PIXEL DATA 8 9 PIXEL DATA 9 x3072

BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 2 PIXEL DATA 2 3 PIXEL DATA 3 4 PIXEL DATA 4 5 PIXEL DATA 5 6 PIXEL DATA 6 7 PIXEL DATA 7 8 PIXEL DATA 8 9 PIXEL DATA 9 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC offset: 3754 8 PIXEL DATA 8 9 PIXEL DATA 9

BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 2 PIXEL DATA 2 3 PIXEL DATA 3 4 PIXEL DATA 4 5 PIXEL DATA 5 6 PIXEL DATA 6 7 PIXEL DATA 7 8 PIXEL DATA 8 9 PIXEL DATA 9 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC offset: 3754

BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 2 PIXEL DATA 2 3 PIXEL DATA 3 4 PIXEL DATA 4 5 PIXEL DATA 5 6 PIXEL DATA 6 7 PIXEL DATA 7 8 PIXEL DATA 8 9 PIXEL DATA 9 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC offset: 3754 ???

BufferedSource 2 PIXEL DATA 2 3 PIXEL DATA 3 4 PIXEL DATA 4 5 PIXEL DATA 5 6 PIXEL DATA 6 7 PIXEL DATA 7 8 PIXEL DATA 8 9 PIXEL DATA 9 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC offset: 3754 ???

BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream

BitmapFactory InputStream BufferedSource 2 PIXEL DATA 2 3 PIXEL DATA 3 4 PIXEL DATA 4 5 PIXEL DATA 5 6 PIXEL DATA 6 7 PIXEL DATA 7 8 PIXEL DATA 8 9 PIXEL DATA 9 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC

BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream

BitmapFactory InputStream BufferedSource 2 PIXEL DATA 2 3 PIXEL DATA 3 4 PIXEL DATA 4 5 PIXEL DATA 5 6 PIXEL DATA 6 7 PIXEL DATA 7 8 PIXEL DATA 8 9 PIXEL DATA 9 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC

BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream

BitmapFactory InputStream BufferedSource 2 PIXEL DATA 2 3 PIXEL DATA 3 4 PIXEL DATA 4 5 PIXEL DATA 5 6 PIXEL DATA 6 7 PIXEL DATA 7 8 PIXEL DATA 8 9 PIXEL DATA 9 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC

BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream

BitmapFactory InputStream BufferedSource 2 PIXEL DATA 2 3 PIXEL DATA 3 4 PIXEL DATA 4 5 PIXEL DATA 5 6 PIXEL DATA 6 7 PIXEL DATA 7 8 PIXEL DATA 8 9 PIXEL DATA 9

BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream

BitmapFactory InputStream BufferedSource 5 PIXEL DATA 5 6 PIXEL DATA 6 7 PIXEL DATA 7 8 PIXEL DATA 8 9 PIXEL DATA 9

BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream

BitmapFactory InputStream BufferedSource 8 PIXEL DATA 8 9 PIXEL DATA 9

BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream

BitmapFactory InputStream BufferedSource

BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream

BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream offset: 0

BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 1 METADATA 1 MAGIC offset: 0

BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 1 METADATA 1 MAGIC offset: 341 1 METADATA 1 MAGIC

BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 1 METADATA 1 MAGIC offset: 341 1 METADATA 1 MAGIC

BitmapFactory inJustDecodeBounds=true BufferedSource SourceBufferingInputStream 1 METADATA 1 MAGIC offset: 341 1 METADATA 1 MAGIC 1920x1080

BufferedSource 1 METADATA 1 MAGIC offset: 341 1920x1080 1METADATA 1 MAGIC

BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream

ExifInterface BufferedSource SourceBufferingInputStream 1 METADATA 1 MAGIC offset: 341 1920x1080 offset: 0 1METADATA 1 MAGIC

BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream

ExifInterface BufferedSource SourceBufferingInputStream 1 METADATA 1 MAGIC offset: 341 1920x1080 offset: 341 1 METADATA 1 MAGIC 1METADATA 1 MAGIC

BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream

ExifInterface BufferedSource SourceBufferingInputStream 1 METADATA 1 MAGIC offset: 341 1920x1080 offset: 341 1 METADATA 1 MAGIC 1METADATA 1 MAGIC

BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream

ExifInterface BufferedSource SourceBufferingInputStream 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC offset: 341 1920x1080 offset: 341 1METADATA 1 MAGIC

BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream

ExifInterface BufferedSource SourceBufferingInputStream 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC offset: 341 1920x1080 offset: 1024 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 341 1METADATA 1 MAGIC

BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream

ExifInterface BufferedSource SourceBufferingInputStream 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC offset: 341 1920x1080 offset: 1024 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 341 1METADATA 1 MAGIC

BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream

ExifInterface BufferedSource SourceBufferingInputStream 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC offset: 341 1920x1080 offset: 1024 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 341 90 ° 1METADATA 1 MAGIC

BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream

BufferedSource 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC offset: 341 1920x1080 341 90 °

1METADATA 1 MAGIC

BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream offset: 1024 1PIXEL DATA 1 3METADATA 3 2METADATA 2 ExifInterface SourceBufferingInputStream

BitmapFactory InputStream BufferedSource 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC offset: 341 1920x1080 341 90 °

1METADATA 1 MAGIC

BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream offset: 1024 1PIXEL DATA 1 3METADATA 3 2METADATA 2 ExifInterface SourceBufferingInputStream

BitmapFactory InputStream BufferedSource 2 PIXEL DATA 2 3 PIXEL DATA 3 4 PIXEL DATA 4 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC offset: 341 1920x1080 341 90 °

1METADATA 1 MAGIC

BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream offset: 1024 1PIXEL DATA 1 3METADATA 3 2METADATA 2 ExifInterface SourceBufferingInputStream

BitmapFactory InputStream BufferedSource 2 PIXEL DATA 2 3 PIXEL DATA 3 4 PIXEL DATA 4 5 PIXEL DATA 5 6 PIXEL DATA 6 7 PIXEL DATA 7 1 PIXEL DATA 1 3 METADATA 3 2 METADATA 2 1 METADATA 1 MAGIC offset: 341 1920x1080 341 90 °

1METADATA 1 MAGIC

BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream offset: 1024 1PIXEL DATA 1 3METADATA 3 2METADATA 2 ExifInterface SourceBufferingInputStream

BitmapFactory InputStream BufferedSource 2 PIXEL DATA 2 3 PIXEL DATA 3 4 PIXEL DATA 4 5 PIXEL DATA 5 6 PIXEL DATA 6 7 PIXEL DATA 7 8 PIXEL DATA 8 9 PIXEL DATA 9 offset: 341 1920x1080 341 90 °

1METADATA 1 MAGIC

BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream offset: 1024 1PIXEL DATA 1 3METADATA 3 2METADATA 2 ExifInterface SourceBufferingInputStream

BitmapFactory InputStream BufferedSource 5 PIXEL DATA 5 6 PIXEL DATA 6 7 PIXEL DATA 7 8 PIXEL DATA 8 9 PIXEL DATA 9 offset: 341 1920x1080 341 90 °

1METADATA 1 MAGIC

BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream offset: 1024 1PIXEL DATA 1 3METADATA 3 2METADATA 2 ExifInterface SourceBufferingInputStream

BitmapFactory InputStream BufferedSource 8 PIXEL DATA 8 9 PIXEL DATA 9 offset: 341 1920x1080 341 90 °

1METADATA 1 MAGIC

BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream offset: 1024 1PIXEL DATA 1 3METADATA 3 2METADATA 2 ExifInterface SourceBufferingInputStream

BitmapFactory InputStream BufferedSource offset: 341 1920x1080 341 90 °

1METADATA 1 MAGIC

BitmapFactory inJustDecodeBounds=true SourceBufferingInputStream offset: 1024 1PIXEL DATA 1 3METADATA 3 2METADATA 2 ExifInterface SourceBufferingInputStream

BufferedSource offset: 341 SourceBufferingInputStream 341 SourceBufferingInputStream BitmapFactory InputStream

1METADATA 1 MAGIC

BitmapFactory inJustDecodeBounds=true 1920x1080 offset: 1024 1PIXEL DATA 1 3METADATA 3 2METADATA 2 90 ° ExifInterface

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

Picasso picasso .load(url)

.placeholder(R.drawable. placeholder )

.error(R.drawable. error )

.fit()

.into(view) ;

Picasso

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

Picasso fun loadImage ( awsAssetUri: Uri ,

height: Int ,

width: Int

) {

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

Picasso fun loadImage ( awsAssetUri: Uri ,

height: Int ,

width: Int

) {

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

Picasso picasso .load( “http://shrek.jpg” )

.placeholder(R.drawable. placeholder )

.error(R.drawable. error )

.fit()

.into(view) ;

Picasso “http://shrek.jpg” Request

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

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

http://shrek.jpg

01010110101001101 http://shrek.jpg

01010110101001101 http://shrek.jpg

01010110101001101

01010110101001101

01010110101001101

01 01 0110 10100 1 1 0 1

01 01 0110 10100 1 1 0 1

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

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

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

0101011

0101011

0101011

0101011

0101011

01 010 1 1

01 010 1 1

01 010 1 1

?

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

Picasso Request Transformer

ResourceRequestHandler NetworkRequestHandler FileRequestHandler Picasso Request Transformer AssetsRequestHandler

Picasso Request Transformer Handler Request

Picasso Request Transformer Request Handler Bitmap

Bitmap Drawable Result Picasso Request Transformer Request Handler

Picasso Request Transformer Result Request Handler

Picasso Request Transformer Result Request Handler Greyscale Circle Tint

Picasso Request Transformer Result Request Handler Transformation Greyscale Circle Tint

Picasso Request Transformer Result Request Handler Transformation

Picasso Request Transformer Result Target Request Handler Transformation

Request Transformer Result Request Handler Transformation

Transformer Result Transformer Transformer

Transformer Transformer Transformer

Transformer Transformer Transformer

Transformer Transformer Transformer

Transformer Transformer Transformer

Transformer Transformer Transformer

square/okhttp

custom interceptors Retry Bridge Cache Connect Call Server square/okhttp

custom interceptors Retry Bridge Cache Connect Call Server square/okhttp

custom interceptors Retry Bridge Cache Connect Call Server square/okhttp

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

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

public static Picasso with (Context context) {

if ( singleton

null ) {

synchronized (Picasso. class ) {

if ( singleton

null ) {

singleton

new Builder(context).build() ;

} } }

return singleton ; }

public static Picasso with (Context context) {

if ( singleton

null ) {

synchronized (Picasso. class ) {

if ( singleton

null ) {

singleton

new Builder(context).build() ;

} } }

return singleton ; }

public static void setSingletonInstance (Picasso picasso) {

synchronized (Picasso. class ) {

if ( singleton != null ) {

throw new IllegalStateException(

"Singleton instance already exists." ) ;

}

singleton = picasso ;

} }

public static void setSingletonInstance (Picasso picasso) {

synchronized (Picasso. class ) {

if ( singleton != null ) {

throw new IllegalStateException(

"Singleton instance already exists." ) ;

}

singleton = picasso ;

} }

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

} }

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

} }

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 ;

} }

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 ;

} }

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 ;

} }

public final class PicassoContentProvider extends ContentProvider {

static Context context ;

@Override public boolean onCreate () {

context = getContext() ; return true;

}

…

}

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

Picasso. with (context) X

.load(url)

.placeholder(R.drawable. placeholder )

.error(R.drawable. error )

.fit()

.into(view) ;

PicassoProvider. get () X

.load(url)

.placeholder(R.drawable. placeholder )

.error(R.drawable. error )

.fit()

.into(view) ;

with context

picasso .load(url)

.placeholder(R.drawable. placeholder )

.error(R.drawable. error )

.fit()

.into(view) ;

abstract class RequestHandler {

abstract boolean canHandleRequest (Request request) ;

abstract Result

load (Request request , int networkPolicy) ; } X

abstract class RequestHandler {

abstract boolean canHandleRequest (Request request) ;

abstract void load (Picasso

picasso ,

Request

request ,

Callback

callback) ; } X

Result int networkPolicy

Coming Soon

• Better separation of concerns: Source/Target/Load Coming Soon

• Better separation of concerns: Source/Target/Load • Propagating Drawables to Target (animated GIFs!) Coming Soon

• Better separation of concerns: Source/Target/Load • Propagating Drawables to Target (animated GIFs!) • More? Let us know! Coming Soon

PICASSO WILL RETURN 3.0

Rinsing the Brush: Picasso 3.0 @jrodbx @JakeWharton