Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b967392e authored by Adam Cohen's avatar Adam Cohen
Browse files

Hinting RemoteViewsAdapter as to which views are visible

-> This prevents collection widgets from flashing loading
   views when they are updated with new content

Change-Id: I1241ff9a09edfd990ad03f76449d18b9359246b4
parent d9bb7a8d
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -5571,6 +5571,16 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
        // items from the Adapter.
    }

    /**
     * Hints the RemoteViewsAdapter, if it exists, about which views are currently
     * being displayed by the AbsListView.
     */
    void setVisibleRangeHint(int start, int end) {
        if (mRemoteAdapter != null) {
            mRemoteAdapter.setVisibleRangeHint(start, end);
        }
    }

    /**
     * Sets the recycler listener to be notified whenever a View is set aside in
     * the recycler for later reuse. This listener can be used to free resources
+3 −0
Original line number Diff line number Diff line
@@ -555,6 +555,9 @@ public abstract class AdapterViewAnimator extends AdapterView<Adapter>
            mCurrentWindowStart = newWindowStart;
            mCurrentWindowEnd = newWindowEnd;
            mCurrentWindowStartUnbounded = newWindowStartUnbounded;
            if (mRemoteViewsAdapter != null) {
                mRemoteViewsAdapter.setVisibleRangeHint(mCurrentWindowStart, mCurrentWindowEnd);
            }
        }
        requestLayout();
        invalidate();
+2 −0
Original line number Diff line number Diff line
@@ -290,6 +290,7 @@ public class GridView extends AbsListView {
            pos += mNumColumns;
        }

        setVisibleRangeHint(mFirstPosition, mFirstPosition + getChildCount() - 1);
        return selectedView;
    }

@@ -382,6 +383,7 @@ public class GridView extends AbsListView {
            mFirstPosition = Math.max(0, pos + 1);
        }

        setVisibleRangeHint(mFirstPosition, mFirstPosition + getChildCount() - 1);
        return selectedView;
    }

+2 −1
Original line number Diff line number Diff line
@@ -678,6 +678,7 @@ public class ListView extends AbsListView {
            pos++;
        }

        setVisibleRangeHint(mFirstPosition, mFirstPosition + getChildCount() - 1);
        return selectedView;
    }

@@ -711,7 +712,7 @@ public class ListView extends AbsListView {
        }

        mFirstPosition = pos + 1;

        setVisibleRangeHint(mFirstPosition, mFirstPosition + getChildCount() - 1);
        return selectedView;
    }

+30 −9
Original line number Diff line number Diff line
@@ -68,6 +68,8 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
    private RemoteViewsAdapterServiceConnection mServiceConnection;
    private WeakReference<RemoteAdapterConnectionCallback> mCallback;
    private FixedSizeRemoteViewsCache mCache;
    private int mVisibleWindowLowerBound;
    private int mVisibleWindowUpperBound;

    // A flag to determine whether we should notify data set changed after we connect
    private boolean mNotifyDataSetChangedAfterOnServiceConnected = false;
@@ -765,7 +767,7 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
                    }
                    if (position > -1) {
                        // Load the item, and notify any existing RemoteViewsFrameLayouts
                        updateRemoteViews(position, isRequested);
                        updateRemoteViews(position, isRequested, true);

                        // Queue up for the next one to load
                        loadNextIndexInBackground();
@@ -827,8 +829,8 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
        }
    }

    private void updateRemoteViews(final int position, boolean isRequested) {
        if (!mServiceConnection.isConnected()) return;
    private void updateRemoteViews(final int position, boolean isRequested, boolean
            notifyWhenLoaded) {
        IRemoteViewsFactory factory = mServiceConnection.getRemoteViewsFactory();

        // Load the item information from the remote service
@@ -864,6 +866,7 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
            // there is new data for it.
            final RemoteViews rv = remoteViews;
            final int typeId = mCache.getMetaDataAt(position).typeId;
            if (notifyWhenLoaded) {
                mMainQueue.post(new Runnable() {
                    @Override
                    public void run() {
@@ -872,6 +875,7 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
                });
            }
        }
    }

    public Intent getRemoteViewsServiceIntent() {
        return mIntent;
@@ -929,6 +933,16 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
        return typeId;
    }

    /**
     * This method allows an AdapterView using this Adapter to provide information about which
     * views are currently being displayed. This allows for certain optimizations and preloading
     * which  wouldn't otherwise be possible.
     */
    public void setVisibleRangeHint(int lowerBound, int upperBound) {
        mVisibleWindowLowerBound = lowerBound;
        mVisibleWindowUpperBound = upperBound;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        // "Request" an index so that we can queue it for loading, initiate subsequent
        // preloading, etc.
@@ -1059,6 +1073,13 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
        // Re-request the new metadata (only after the notification to the factory)
        updateTemporaryMetaData();

        // Pre-load (our best guess of) the views which are currently visible in the AdapterView.
        // This mitigates flashing and flickering of loading views when a widget notifies that
        // its data has changed.
        for (int i = mVisibleWindowLowerBound; i <= mVisibleWindowUpperBound; i++) {
            updateRemoteViews(i, false, false);
        }

        // Propagate the notification back to the base adapter
        mMainQueue.post(new Runnable() {
            @Override