A presentation at Chicago Roboto in in Chicago, IL, USA by Jake Wharton
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) {
null ) {
synchronized (Picasso. class ) {
null ) {
new Builder(context).build() ;
} } }
return singleton ; }
public static Picasso with (Context context) {
null ) {
synchronized (Picasso. class ) {
null ) {
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 () {
null ) {
synchronized (PicassoProvider. class ) {
null ) {
null ) {
throw new IllegalStateException( "context == null" ) ;
}
new
Picasso.Builder(PicassoContentProvider. context ).build() ;
} } }
return instance ;
} }
public final class PicassoProvider {
private static volatile Picasso instance ; public static Picasso get () {
null ) {
synchronized (PicassoProvider. class ) {
null ) {
null ) {
throw new IllegalStateException( "context == null" ) ;
}
new
Picasso.Builder(PicassoContentProvider. context ).build() ;
} } }
return instance ;
} }
public final class PicassoProvider {
private static volatile Picasso instance ; public static Picasso get () {
null ) {
synchronized (PicassoProvider. class ) {
null ) {
null ) {
throw new IllegalStateException( "context == null" ) ;
}
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
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:
You’ll learn to efficiently work with different image formats across millions of devices!
Presented with John Rodriguez