Volley字节换冲池的使用_ByteArrayPool

原理:

当需要使用byte[]的时候从缓冲池中获取,如果没有合适的大小,则根据指定大小创建一个新的byte[],使用完成后可在mSizeLimit的限制下缓存到缓冲池中;

目的:

我们知道在gc的过程中可能会阻塞主线程,因此尽量避免产生大量的堆信息从而减少gc操作,对我们app的性能改善是很有帮助的;那么使用缓冲池的目的是为了解决在byte[]的创建中产生大量的堆信息以及在gc过程中的延迟,从而改善app的性能;

使用场景:

一些I/O操作,比如网络操作,每次数据的解析将会产生大量的不同大小的byte[]对象,如果能够某个范围类将使用的过的byte[]对象缓存起来,方便以后使用,那么对app性能的提升有很大的改善;

源码分析:

ByteArrayPool类中关键字段:mBuffersByLastUse、mBuffersBySize、mCurrentSize、mSizeLimit;根据字面意思就能够理解,这里就不在多说;

首先看获得buffer的方法,getBuf(int len);根据指定的大小从缓冲池中获得buffer(该buffer可能比指定的len要大),否则创建一个新的buffer;

    /**
     * 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.
     *
     * @param len the minimum size, in bytes, of the requested buffer. The returned buffer may be
     *        larger.
     * @return 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];
    }

buffer使用完成后缓存到该缓冲池中,方法为returnBuf(byte[] buf);如果buf大于mSizeLimit则不缓存,否则将buf放入mBuffersByLastUse中,然后根据Collections.binarySearch()查找在mBuffersBySize的位置,并添加到mBuffersBySize中,再调用trim()方法:

    /**
     * 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);
        int pos = Collections.binarySearch(mBuffersBySize, buf, BUF_COMPARATOR);
        if (pos < 0) {
            pos = -pos - 1;
        }
        mBuffersBySize.add(pos, buf);
        mCurrentSize += buf.length;
        trim();
    }

trim()方法的作用:如果mCurrentSize 大于mSizeLimit,则从mBuffersByLastUse和mBuffersBySize中移除部分buffer,直到mCurrentSize 在mSizeLimit限制范围内;

    /**
     * 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;
        }
    }

该类的使用主要结合了PoolingByteArrayOutputStream类,在Volley中体现在BasicNetwork的entityToBytes(HttpEntity entity)方法中,代码如下:

    /** 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();
        }
    }

总结:

在我们app的开发中为什么推荐使用volley呢?就是因为volley在一些细节上做得比较好,考虑得比较周全,对我们的app的性能提升有一定的帮助;

现在做Android app开发很多人都觉得比较简单,用一些开源的工具进行组合就能够将我们的app开发出来,但是如果需要做一个精细化高性能的app还是需要技术含量的,需要对底层及原理有一定的了解。希望大家在app的开发过程中做一定的性能优化,提升app的流畅度,提供更好的用户体验。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值