PUBLIC OBJECT

InputStream mark() and reset() are handy, but broken.

The API is limited to saving a single position in a stream. Suppose Picasso marks a position in a bitmap stream, then calls BitmapFactory to process that stream. Since BitmapFactory itself calls mark() and reset(), it clobbers Picasso's mark position and things break when Picasso calls reset().

The Java NIO ByteBuffer classes suffer the same broken design. Each buffer has a single position, limit and mark, and if you pass your ByteBuffer to another method, that method may clobber your cursors. Arrays are easier to work with because each cursor is just an int!

Last night I wrote a fun class for Picasso. It's an InputStream that permits an unlimited number of mark/reset positions. Like array indices, each marked position is just an offset into the stream.

This silly test shows two overlapping cursors, one called must and another called stang:

    MarkableInputStream in = new MarkableInputStream(
        new ByteArrayInputStream("ford mustang".getBytes(ASCII)));
    assertThat(readBytes(in, 5)).isEqualTo("ford ");
    long must = in.savePosition(4);
    assertThat(readBytes(in, 2)).isEqualTo("mu");
    long stang = in.savePosition(5);
    assertThat(readBytes(in, 4)).isEqualTo("stan");
    in.reset(stang);
    assertThat(readBytes(in, 1)).isEqualTo("s");
    in.reset(must);
    assertThat(readBytes(in, 7)).isEqualTo("mustang");

I thought it was a lot of fun to write!

And thanks to Jake Wharton and Dimitris Koutsogiorgas, Picasso will load bitmaps scaled to the right size without any unnecessary I/O. If you're showing images in your Android app, you should show them with Picasso.