Android native Gallery3d optimization series--1

It has not been updated for a long time, starting today a series of records about the learning, optimization and problem solving of Android's native Gallery3d.

When there are many Albums, if you slide quickly, you will find that it takes a long time to display the data. This is because when the
ReloadTask in AlbumSetDataLoader loads data, it starts loading from (mContentStart, mContentEnd) within this range, rather than loading it first. Visible range (mActiveStart, mActiveEnd) and the great god of Google had already realized this when he wrote this code, but it was not completed, leaving TODO
// TODO: load active range first

So we found the problem and optimized it First load [mActiveStart, mActiveEnd] and then load (mContentStart, mActiveStart) and (mActiveEnd, mActiveEnd)

private int getInvalidIndex(long version) {
            long setVersion[] = mSetVersion;
            int length = setVersion.length;

            //load active range first
            for (int i = mActiveStart, n = mActiveEnd; i < n; ++i) {
                if (setVersion[i % length] != version){
                    return i;
                }
            }

            //load mContentStart ~ mActiveStart
            for (int i = mContentStart; i < mActiveStart; ++i) {
                if (setVersion[i % length] != version){
                    return i;
                }
            }

            //load mActiveEnd ~ mContentEnd
            for (int i = mActiveEnd; i < mContentEnd; ++i) {
                if (setVersion[i % length] != version){
                    return i;
                }
            }
            return INDEX_NONE;
        }

Although we have modified this above, the mActiveStart and mActiveEnd in AlbumSetDataLoader are not correctly assigned, so we also need to modify AlbumSettSlidingWindow.java
private void setContentWindow(int contentStart, int contentEnd) {
        if (contentStart == mContentStart && contentEnd == mContentEnd){
            return;
        }

        if (contentStart >= mContentEnd || mContentStart >= contentEnd) {
            for (int i = mContentStart, n = mContentEnd; i < n; ++i) {
                freeSlotContent (i);
            }
            mSource.setContentWindow(contentStart, contentEnd);
            for (int i = contentStart; i < contentEnd; ++i) {
                prepareSlotContent(i);
            }
        } else {
            for (int i = mContentStart; i < contentStart; ++i) {
                freeSlotContent (i);
            }
            for (int i = contentEnd, n = mContentEnd; i < n; ++i) {
                freeSlotContent (i);
            }
            mSource.setContentWindow(contentStart, contentEnd);
            for (int i = contentStart, n = mContentStart; i < n; ++i) {
                prepareSlotContent(i);
            }
            for (int i = mContentEnd; i < contentEnd; ++i) {
                prepareSlotContent(i);
            }
        }

        mContentStart = contentStart;
        mContentEnd = contentEnd;
    }

    public void setActiveWindow(int start, int end) {
        if (!(start <= end && end - start <= mData.length && end <= mSize)) {
            Utils.fail("start = %s, end = %s, length = %s, size = %s",
                    start, end, mData.length, mSize);
        }

        AlbumSetEntry data[] = mData;
        mActiveStart = start;
        mActiveEnd = end;
        mSource.setActiveWindow(mActiveStart, mActiveEnd);
        int contentStart = Utils.clamp((start + end) / 2 - data.length / 2,
                0, Math.max(0, mSize - data.length));
        int contentEnd = Math.min(contentStart + data.length, mSize);
        setContentWindow(contentStart,contentEnd);

        if (mIsActive) {
            updateTextureUploadQueue();
            updateAllImageRequests();
        }
    }


It also needs to be modified in AlbumSetDataLoader as follows
public void setContentWindow(int startContent, int endContent) {
        int length = mCoverItem.length;
        // If no data is visible, keep the cache content
        if (startContent == endContent) {
            return;
        }

        int contentStart = Utils.clamp((startContent + endContent) / 2 - length / 2,
                0, Math.max(0, mSize - length));
        int contentEnd = Math.min(contentStart + length, mSize);
        if (mContentStart > startContent || mContentEnd < endContent
                || Math.abs(contentStart - mContentStart) > MIN_LOAD_COUNT) {
            if (contentStart == mContentStart && contentEnd == mContentEnd) {
                return;
            }

            int start = this.mContentStart;
            int end = this.mContentEnd;

            mContentStart = contentStart;
            mContentEnd = contentEnd;

            if (contentStart >= end || start >= contentEnd) {
                for (int i = start; i < end; ++i) {
                    clearSlot(i % length);
                }
            } else {
                for (int i = start; i < contentStart; ++i) {
                    clearSlot(i % length);
                }
                for (int i = contentEnd; i < end; ++i) {
                    clearSlot(i % length);
                }
            }
            mReloadTask.notifyDirty();
        }

    }

    public void setActiveWindow(int start, int end) {
        if (start == mActiveStart && end == mActiveEnd){
            return;
        }

        Utils.assertTrue(start <= end
                && end - start <= mCoverItem.length && end <= mSize);

        mActiveStart = start;
        mActiveEnd = end;


    }


dangAlbumDataLoader agrees that there is such a problem, but mActiveStart and mActiveEnd are normally assigned, so just modify the first getInvalidIndex according to AlbumSetDataLoader.

This optimization and article are implemented by me. If you want to reprint, please indicate the source, thank you!

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326262861&siteId=291194637