Android Glide 3, app keep alive interview questions


[Android Glide 3.7.0 source code analysis (VII), detailed graphics transformation and decoding](

)The role of RecyclableBufferedInputStream in mark(int marklimit) and reset() methods has been mentioned. This paper discusses the specific implementation ideas

mark(int marklimit) is used to create a repeatable read area in the stream whose starting point is markPos and length is markLimit. When the reset() method is called, the read position of the stream will return to markPos to realize that markLimit can be read repeatedly

be careful:

  • When the read position reaches readPos_2, the reset() method will fail because it has exceeded the length range of markLimit
  • The starting point markPos of mark(int marklimit) mark is the read position of the stream during method call (when mark in the above figure, the read position is readPos_0, so markPos == readPos_0)

We all know that a Stream can only be read once

2, Realization idea

The above diagram is just a black box operation route view. Let's analyze the specific implementation diagram Since InputStream can only be read once and consumed, we must use an external tool to repeat reading. Here is buf a byte [] array with an initial size of 64K. The elements in the above figure are described below

  • On the right is unread data that still exists in the InputStream
  • On the left is the data that has been read from the process and stored in buf
  • count represents the number of valid data in the buf (if you read to the end of the stream, the buf may be dissatisfied with reading)
  • markpos represents the position of the mark()
  • The blue bar is the part that needs to be read repeatedly. marklimit indicates its length
  • pos represents the location currently being read

Now that we have buf as the cache, we can cache the stream data of mark in buf, so that we can read it repeatedly

Note: the buf size is not constant. When marklimit > buf.length and some other conditions are met, the buf will be expanded twice

3, Source code analysis

Look at the variables of RecyclableBufferedInputStream (in fact, I talked about them when I introduced the idea)

public class RecyclableBufferedInputStream extends FilterInputStream {
  	// buf caches the data read from the stream
    private volatile byte[] buf;
    // buf length of valid data
    private int count;
    // mark marks the length of the data
    private int marklimit;
    // Mark is the location of the mark. The default value of - 1 indicates that there is no mark
    private int markpos = -1;
    // Current read buf location
    private int pos;

mark() and reset()

Let's look at the mark and reset methods

 public synchronized void mark(int readlimit) {
        marklimit = Math.max(marklimit, readlimit);
        markpos = pos;
	public synchronized void reset() throws IOException {
        if (buf == null) {
            throw new IOException("Stream is closed");
        if (-1 == markpos) {
            throw new InvalidMarkException("Mark has been invalidated");
        pos = markpos;

mark did two things: assignment + assignment

  • Mark limit is compared with the old one to get a maximum value
  • Set markpos to the current reading position

reset did one thing

  • The current position pos is reset to markpos


Let's see what the read method does

 public synchronized int read() throws IOException {
        // Use local refs since buf and in may be invalidated by an
        // unsynchronized close()
        byte[] localBuf = buf;
        InputStream localIn = in;
        if (localBuf == null || localIn == null) {
            throw streamClosed();

        // Are there buffered bytes available?
        if (pos >= count && fillbuf(localIn, localBuf) == -1) {
            // no, fill buffer
            return -1;
        // localBuf may have been invalidated by fillbuf
        if (localBuf != buf) {
            localBuf = buf;
            if (localBuf == null) {
                throw streamClosed();

        // Did filling the buffer fail with -1 (EOF)?
        if (count - pos > 0) {
            return localBuf[pos++] & 0xFF;
        return -1;

This read() method is used to read a single character. It is read-only and returns 1 byte at a time

  • POS > = count means that the buf has been read. Call fillbuf(localIn, localBuf) to refill the buf with data
  • Count - POS > 0 means buf data is enough. Read directly and return localbuf [POS + +] & 0xff

return here is an int??? The good byte is that the returned stream data has an unsigned byte range of 0 ~ 255, while the byte in java has a signed range of - 128 ~ 127 by default. The data range is not enough and can only be rounded up with int. note that this line of code: localbuf [POS + +] & 0xff clears all the upper 24 bits to achieve the effect of returning 0 ~ 255

It seems that there is no mention of mark in the middle. I guess it can only be implemented in the fillbuf function. Follow in and have a look


The code is long. Be patient

 private int fillbuf(InputStream localIn, byte[] localBuf)
            throws IOException {
		// If there is no tag or the read area exceeds the range of the tag, read the data directly from the stream to the buf
        if (markpos == -1 || pos - markpos >= marklimit) {
            // Mark position not set or exceeded readlimit
            int result =;
            if (result > 0) {
                markpos = -1;
                pos = 0;
                count = result;
            return result;
        // [valid flag] buf.length here is not enough. Expand the capacity by 2 times
        if (markpos == 0 && marklimit > localBuf.length && count == localBuf.length) {
        // [valid flag] buf.length here is not enough. Expand the capacity by 2 times
        if (markpos == 0 && marklimit > localBuf.length && count == localBuf.length) {

Tags: Android Design Pattern Algorithm Interview Programmer

Posted on Sun, 21 Nov 2021 05:18:54 -0500 by Gmunky