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

Commit 39bed695 authored by Alan Viverette's avatar Alan Viverette
Browse files

Fix FastScroller regression for non-UI threads

Previously it was safe to call setFastScrollEnabled() and
setFastScrollAlwaysVisible() off the UI thread. After switching
FastScroller to use an Overlay, these methods stopped working.

This change ensures that all direct interaction with FastScroller
happens on the thread that created the host AbsListView.

BUG: 10210504
Change-Id: Ib6d9bd9212965420c0de39546652e3bc2d32ff8b
parent 18ec40c4
Loading
Loading
Loading
Loading
+59 −11
Original line number Diff line number Diff line
@@ -222,6 +222,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
     */
    public static final int CHOICE_MODE_MULTIPLE_MODAL = 3;

    /**
     * The thread that created this view.
     */
    private final Thread mOwnerThread;

    /**
     * Controls if/how the user may choose/check items in the list
     */
@@ -437,6 +442,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
     */
    boolean mFastScrollEnabled;

    /**
     * Whether or not to always show the fast scroll feature on this list
     */
    boolean mFastScrollAlwaysVisible;

    /**
     * Optional callback to notify client when scroll position has changed
     */
@@ -756,6 +766,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
        super(context);
        initAbsListView();

        mOwnerThread = Thread.currentThread();

        setVerticalScrollBarEnabled(true);
        TypedArray a = context.obtainStyledAttributes(R.styleable.View);
        initializeScrollbars(a);
@@ -770,6 +782,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
        super(context, attrs, defStyle);
        initAbsListView();

        mOwnerThread = Thread.currentThread();

        TypedArray a = context.obtainStyledAttributes(attrs,
                com.android.internal.R.styleable.AbsListView, defStyle, 0);

@@ -1205,15 +1219,28 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
     * @see #isFastScrollEnabled()
     * @param enabled whether or not to enable fast scrolling
     */
    public void setFastScrollEnabled(boolean enabled) {
    public void setFastScrollEnabled(final boolean enabled) {
        if (mFastScrollEnabled != enabled) {
            mFastScrollEnabled = enabled;

        if (enabled && mFastScroller == null) {
            mFastScroller = new FastScroller(getContext(), this);
            if (isOwnerThread()) {
                setFastScrollerEnabledUiThread(enabled);
            } else {
                post(new Runnable() {
                    @Override
                    public void run() {
                        setFastScrollerEnabledUiThread(enabled);
                    }
                });
            }
        }
    }

    private void setFastScrollerEnabledUiThread(boolean enabled) {
        if (mFastScroller != null) {
            mFastScroller.setEnabled(enabled);
        } else if (enabled) {
            mFastScroller = new FastScroller(this);
        }
    }

@@ -1228,17 +1255,38 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
     * @see #setScrollBarStyle(int)
     * @see #setFastScrollEnabled(boolean)
     */
    public void setFastScrollAlwaysVisible(boolean alwaysShow) {
    public void setFastScrollAlwaysVisible(final boolean alwaysShow) {
        if (mFastScrollAlwaysVisible != alwaysShow) {
            if (alwaysShow && !mFastScrollEnabled) {
                setFastScrollEnabled(true);
            }

            mFastScrollAlwaysVisible = alwaysShow;

            if (isOwnerThread()) {
                setFastScrollerAlwaysVisibleUiThread(alwaysShow);
            } else {
                post(new Runnable() {
                    @Override
                    public void run() {
                        setFastScrollerAlwaysVisibleUiThread(alwaysShow);
                    }
                });
            }
        }
    }

    private void setFastScrollerAlwaysVisibleUiThread(boolean alwaysShow) {
        if (mFastScroller != null) {
            mFastScroller.setAlwaysShow(alwaysShow);
        }
    }

        computeOpaqueFlags();
        recomputePadding();
    /**
     * @return whether the current thread is the one that created the view
     */
    private boolean isOwnerThread() {
        return mOwnerThread == Thread.currentThread();
    }

    /**
@@ -1249,12 +1297,12 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
     * @see #setFastScrollAlwaysVisible(boolean)
     */
    public boolean isFastScrollAlwaysVisible() {
        return mFastScrollEnabled && mFastScroller.isAlwaysShowEnabled();
        return mFastScrollEnabled && mFastScrollAlwaysVisible;
    }

    @Override
    public int getVerticalScrollbarWidth() {
        if (isFastScrollAlwaysVisible()) {
        if (isFastScrollAlwaysVisible() && mFastScroller != null) {
            return Math.max(super.getVerticalScrollbarWidth(), mFastScroller.getWidth());
        }
        return super.getVerticalScrollbarWidth();
+2 −1
Original line number Diff line number Diff line
@@ -231,10 +231,11 @@ class FastScroller {
        }
    };

    public FastScroller(Context context, AbsListView listView) {
    public FastScroller(AbsListView listView) {
        mList = listView;
        mOverlay = listView.getOverlay();

        final Context context = listView.getContext();
        mScaledTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();

        final Resources res = context.getResources();