Volley周边

1 volley

工作原理:

源码
git clone https://android.googlesource.com/platform/frameworks/volley

2 SHA-1值的获取

class InternalUtils {

    // http://stackoverflow.com/questions/9655181/convert-from-byte-array-to-hex-string-in-java
    private final static char[] HEX_CHARS = "0123456789ABCDEF".toCharArray();

    private static String convertToHex(byte[] bytes) {
        char[] hexChars = new char[bytes.length * 2];
        for (int j = 0; j < bytes.length; j++) {
            int v = bytes[j] & 0xFF;
         //“>> 右移,高位补符号位” 这里右移一位表示除2 “>>> 无符号右移,高位补0”;
            hexChars[j * 2] = HEX_CHARS[v >>> 4];
            hexChars[j * 2 + 1] = HEX_CHARS[v & 0x0F];
        }
        return new String(hexChars);
    }

    public static String sha1Hash(String text) {
        String hash = null;
        try {
            final MessageDigest digest = MessageDigest.getInstance("SHA-1");
            final byte[] bytes = text.getBytes("UTF-8");
            digest.update(bytes, 0, bytes.length);
            hash = convertToHex(digest.digest());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return hash;
    }
}

3 Walk up the stack

/** What a Terrible Failure: Report a condition that should never happen. The error will always be logged at level ASSERT with the call stack. Depending on system configuration, a report may be added to the DropBoxManager and/or the process may be terminated immediately with an error dialog. */
    public static void wtf(String format, Object... args) {
        Log.wtf(TAG, buildMessage(format, args));
    }

    /**
     * Formats the caller's provided message and prepends预先考虑 useful info like
     * calling thread ID and method name.
     */
    private static String buildMessage(String format, Object... args) {
        String msg = (args == null) ? format : String.format(Locale.US, format, args);
        StackTraceElement[] trace = new Throwable().fillInStackTrace().getStackTrace();

        String caller = "<unknown>";
        // Walk up the stack looking for the first caller outside of VolleyLog.
        // It will be at least two frames up, so start there.
        for (int i = 2; i < trace.length; i++) {
            Class<?> clazz = trace[i].getClass();
            if (!clazz.equals(VolleyLog.class)) {
                String callingClass = trace[i].getClassName();
                callingClass = callingClass.substring(callingClass.lastIndexOf('.') + 1);
                callingClass = callingClass.substring(callingClass.lastIndexOf('$') + 1);
                caller = callingClass + "." + trace[i].getMethodName();
                break;
            }
        }
        return String.format(Locale.US, "[%d] %s: %s",
                Thread.currentThread().getId(), caller, msg);
    }
// %-4d表示整数至少四位,并且左对齐,即不足时右补空格,而%4d是左补空格
@Override 
// Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作
        protected void finalize() throws Throwable {
            // TODO
        }

4 ByteArrayPool

1 ByteArrayPool

/**
 *  ByteArrayPool is a source and repository库 of byte[] objects. Its purpose is to supply those buffers to consumers who need to use them for a short period of time and then dispose of them处理掉. Simply creating and disposing such buffers in the conventional manner 传统方式can considerable可观 heap churn搅动 and garbage collection delays on Android, which lacks缺乏 good management of short-lived heap objects. It may be advantageous to trade off权衡 some memory in the form of a permanently allocated pool of buffers in order to gain heap performance improvements; that is what this class does.
    A good candidate候选人 user for this class is something like an I/O system that uses large temporary byte[] buffers to copy data around. In these use cases, often the consumer wants the buffer to be a certain minimum size to ensure good performance (e.g. when copying data chunks块 off of a stream), but doesn't mind if the buffer is larger than the minimum. Taking this into account and also to maximize the odds可能性 of being able to reuse a recycled buffer, this class is free to return buffers larger than the requested size. The caller needs to be able to gracefully优雅 deal with getting buffers any size over the minimum.
    If there is not a suitably-sized buffer in its recycling pool when a buffer is requested, this class will allocate a new buffer and return it.
    This class has no special ownership of buffers it creates; the caller is free to take a buffer it receives from this pool, use it permanently, and never return it to the pool; additionally, it is not harmful to return to this pool a buffer that was allocated elsewhere, provided there are no other lingering references挥之不去的引用 to it.
    This class ensures that the total size of the buffers in its recycling pool never exceeds a certain byte limit. When a buffer is returned that would cause the pool to exceed the limit, least-recently-used buffers are disposed.
 */
public class ByteArrayPool {
    /** The buffer pool, arranged both by last use and by buffer size */
    private List<byte[]> mBuffersByLastUse = new LinkedList<byte[]>();
    private List<byte[]> mBuffersBySize = new ArrayList<byte[]>(64);

    /** The total size of the buffers in the pool */
    private int mCurrentSize = 0;

    /**
     * The maximum aggregate合计 size of the buffers in the pool. Old buffers are discarded to stay under this limit.
     */
    private final int mSizeLimit;

    /** Compares buffers by size */
    protected static final Comparator<byte[]> BUF_COMPARATOR = new Comparator<byte[]>() {
        @Override
        public int compare(byte[] lhs, byte[] rhs) {
            return lhs.length - rhs.length;
        }
    };

    /**
     * @param sizeLimit the maximum size of the pool, in bytes
     */
    public ByteArrayPool(int sizeLimit) {
        mSizeLimit = sizeLimit;
    }

    /**
     * Returns a buffer from the pool if one is available in the requested size, or allocates a new one if a pooled one is not available.
Parameters:
 len - the minimum size, in bytes, of the requested buffer. The returned buffer may be larger.
Returns:
    a byte[] buffer is always returned.
     */
    public synchronized byte[] getBuf(int len) {
        for (int i = 0; i < mBuffersBySize.size(); i++) {
            byte[] buf = mBuffersBySize.get(i);
            if (buf.length >= len) {
                mCurrentSize -= buf.length;
                mBuffersBySize.remove(i);
                mBuffersByLastUse.remove(buf);
                return buf;
            }
        }
        return new byte[len];
    }

    /**
     * Returns a buffer to the pool, throwing away old buffers if the pool would exceed its allotted size. 
     * @param buf the buffer to return to the pool.
     */
    public synchronized void returnBuf(byte[] buf) {
        if (buf == null || buf.length > mSizeLimit) {
            return;
        }
        mBuffersByLastUse.add(buf);
  // Performs a binary search for the specified element in the specified sorted list using the specified comparator. The list needs to be already sorted according to the comparator passed. Searching in an unsorted array has an undefined result. It's also undefined which element is found if there are multiple occurrences of the same element.
 //return: the non-negative index of the element, or a negative index which is the -index - 1 where the element would be inserted.
        int pos = Collections.binarySearch(mBuffersBySize, buf, BUF_COMPARATOR);
        if (pos < 0) {
            pos = -pos - 1;
        }
        mBuffersBySize.add(pos, buf);
        mCurrentSize += buf.length;
        trim();
    }

    /**
     * Removes buffers from the pool until it is under its size limit.
     */
    private synchronized void trim() {
        while (mCurrentSize > mSizeLimit) {
            byte[] buf = mBuffersByLastUse.remove(0);
            mBuffersBySize.remove(buf);
            mCurrentSize -= buf.length;
        }
    }

}

2 PoolingByteArrayOutputStream

/**
 * A variation变异 of ByteArrayOutputStream that uses a pool of byte[] buffers instead of always allocating them fresh, saving on heap churn搅动.
 */
public class PoolingByteArrayOutputStream extends ByteArrayOutputStream {
    /**
     * If the PoolingByteArrayOutputStream(ByteArrayPool) constructor is called, this is the default size to which the underlying byte array is initialized.
     */
    private static final int DEFAULT_SIZE = 256;

    private final ByteArrayPool mPool;

    /**
     * Constructs a new PoolingByteArrayOutputStream with a default size. If more bytes are written to this instance, the underlying byte array will expand.
     */
    public PoolingByteArrayOutputStream(ByteArrayPool pool) {
        this(pool, DEFAULT_SIZE);
    }

    /**
     * Constructs a new ByteArrayOutputStream with a default size of size bytes. If more than size bytes are written to this instance, the underlying byte array will expand.
Parameters:
    size - initial size for the underlying byte array. The value will be pinned to a default minimum size.
     */
    public PoolingByteArrayOutputStream(ByteArrayPool pool, int size) {
        mPool = pool;
        buf = mPool.getBuf(Math.max(size, DEFAULT_SIZE)); // buf是父类定义的
    }

    @Override
    public void close() throws IOException {
        mPool.returnBuf(buf);
        buf = null;
        super.close();
    }

    @Override//类的Finalize方法,可以告诉垃圾回收器应该执行的操作
    public void finalize() {
        mPool.returnBuf(buf);
    }

    /**
     * Ensures there is enough space in the buffer for the given number of additional bytes.
     */
    private void expand(int i) {
        /* Can the buffer handle @i more bytes, if not expand it */
        if (count + i <= buf.length) {
            return;
        }
        byte[] newbuf = mPool.getBuf((count + i) * 2);
        System.arraycopy(buf, 0, newbuf, 0, count);
        mPool.returnBuf(buf);
        buf = newbuf;
    }

    @Override
    public synchronized void write(byte[] buffer, int offset, int len) {
        expand(len);
        super.write(buffer, offset, len);
    }

    @Override
    public synchronized void write(int oneByte) {
        expand(1);
        super.write(oneByte);
    }
}

3 use

 /** Reads the contents of HttpEntity into a byte[]. */
    private byte[] entityToBytes(HttpEntity entity) throws IOException, ServerError {
        PoolingByteArrayOutputStream bytes =
                new PoolingByteArrayOutputStream(mPool, (int) entity.getContentLength());
        byte[] buffer = null;
        try {
            InputStream in = entity.getContent();
            if (in == null) {
                throw new ServerError();
            }
            buffer = mPool.getBuf(1024);
            int count;
            while ((count = in.read(buffer)) != -1) {
                bytes.write(buffer, 0, count);
            }
            return bytes.toByteArray();
        } finally {
            try {
                // Close the InputStream and release the resources by "consuming the content".
                entity.consumeContent();
            } catch (IOException e) {
                // This can happen if there was an exception above that left the entity in
                // an invalid state.
                VolleyLog.v("Error occured when calling consumingContent");
            }
            mPool.returnBuf(buffer);
            bytes.close();
        }
    }

5 图片

volley可以进行网络图片获取,而IML则可以本地、资源、网络;

问:volley下已经有了ImageRequest,但是又多了ImageLoader类,原因?
volley默认是DISK缓存,而涉及到图片,如果只用DISK必然效率降低,因此ImageLoader的出现很有必要,因为内部维护了内存缓存的接口,使用者进行扩展即可;

问:gridview不会错位的原因是什么?
如果调用时不注意的话,会出现的,如果记得调用cancel的话,即将请求从队列中移除,那么就没有响应了,就不会了。

问:何时调用?
推荐看下NetworkImageView吧,内部onDetachedFromWindow()和loadImageIfNecessary 都调用了cancel。

    @Override
    protected void onDetachedFromWindow() {
        if (mImageContainer != null) {
            // If the view was bound to an image request, cancel it and clear
            // out the image from the view.
            mImageContainer.cancelRequest(); // -----------------here-------------------
            setImageBitmap(null);
            // also clear out the container so we can reload the image if necessary.
            mImageContainer = null;
        }
        super.onDetachedFromWindow();
    }

6 扩展

两方面:

一是Request的扩展,根据需要继承此类即可

二是网络访问的扩展即HttpStack,同样根据需要重写

7 其它

// Parse date in RFC1123 format if this header contains one
            return DateUtils.parseDate(dateStr).getTime();
// Wed, 14 Oct 2015 07:53:22 GMT+00:00
            headers.put("If-Modified-Since", DateUtils.formatDate(refTime));
      // use caller-provided custom SslSocketFactory, if any, for HTTPS
        if ("https".equals(url.getProtocol()) && mSslSocketFactory != null) {
            ((HttpsURLConnection)connection).setSSLSocketFactory(mSslSocketFactory);
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值