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

Commit f1b0eff0 authored by Dianne Hackborn's avatar Dianne Hackborn Committed by Android (Google) Code Review
Browse files

Merge "Improvements to ListFragment."

parents 016a646c 445646c5
Loading
Loading
Loading
Loading
+31 −3
Original line number Diff line number Diff line
@@ -28030,6 +28030,19 @@
<parameter name="id" type="long">
</parameter>
</method>
<method name="setEmptyText"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="text" type="java.lang.CharSequence">
</parameter>
</method>
<method name="setListAdapter"
 return="void"
 abstract="false"
@@ -28043,6 +28056,21 @@
<parameter name="adapter" type="android.widget.ListAdapter">
</parameter>
</method>
<method name="setListShown"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="shown" type="boolean">
</parameter>
<parameter name="animate" type="boolean">
</parameter>
</method>
<method name="setSelection"
 return="void"
 abstract="false"
@@ -28152,7 +28180,7 @@
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="protected"
 visibility="public"
>
<parameter name="id" type="int">
</parameter>
@@ -223896,7 +223924,7 @@
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="t" type="T">
<parameter name="arg0" type="T">
</parameter>
</method>
</interface>
@@ -247337,7 +247365,7 @@
<method name="availableProcessors"
 return="int"
 abstract="false"
 native="false"
 native="true"
 synchronized="false"
 static="false"
 final="false"
+4 −0
Original line number Diff line number Diff line
@@ -4036,6 +4036,7 @@ public class Activity extends ContextThemeWrapper
    
    final void performStart() {
        mCalled = false;
        mFragments.execPendingActions();
        mInstrumentation.callActivityOnStart(this);
        if (!mCalled) {
            throw new SuperNotCalledException(
@@ -4074,6 +4075,8 @@ public class Activity extends ContextThemeWrapper
    final void performResume() {
        performRestart();
        
        mFragments.execPendingActions();
        
        mLastNonConfigurationInstances = null;
        
        // First call onResume() -before- setting mResumed, so we don't
@@ -4091,6 +4094,7 @@ public class Activity extends ContextThemeWrapper
        mCalled = false;
        
        mFragments.dispatchResume();
        mFragments.execPendingActions();
        
        onPostResume();
        if (!mCalled) {
+35 −2
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package android.app;

import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;

import java.util.ArrayList;

@@ -28,14 +29,30 @@ final class BackStackState implements Parcelable {
    final String mName;
    
    public BackStackState(FragmentManager fm, BackStackEntry bse) {
        mOps = new int[bse.mNumOp*4];
        int numRemoved = 0;
        BackStackEntry.Op op = bse.mHead;
        while (op != null) {
            if (op.removed != null) numRemoved += op.removed.size();
            op = op.next;
        }
        mOps = new int[bse.mNumOp*5 + numRemoved];
        
        op = bse.mHead;
        int pos = 0;
        while (op != null) {
            mOps[pos++] = op.cmd;
            mOps[pos++] = op.fragment.mIndex;
            mOps[pos++] = op.enterAnim;
            mOps[pos++] = op.exitAnim;
            if (op.removed != null) {
                final int N = op.removed.size();
                mOps[pos++] = N;
                for (int i=0; i<N; i++) {
                    mOps[pos++] = op.removed.get(i).mIndex;
                }
            } else {
                mOps[pos++] = 0;
            }
            op = op.next;
        }
        mTransition = bse.mTransition;
@@ -61,6 +78,13 @@ final class BackStackState implements Parcelable {
            op.fragment = f;
            op.enterAnim = mOps[pos++];
            op.exitAnim = mOps[pos++];
            final int N = mOps[pos++];
            if (N > 0) {
                op.removed = new ArrayList<Fragment>(N);
                for (int i=0; i<N; i++) {
                    op.removed.add(fm.mActive.get(mOps[pos++]));
                }
            }
            bse.addOp(op);
        }
        bse.mTransition = mTransition;
@@ -96,6 +120,8 @@ final class BackStackState implements Parcelable {
 * @hide Entry of an operation on the fragment back stack.
 */
final class BackStackEntry implements FragmentTransaction, Runnable {
    static final String TAG = "BackStackEntry";
    
    final FragmentManager mManager;
    
    static final int OP_NULL = 0;
@@ -265,11 +291,14 @@ final class BackStackEntry implements FragmentTransaction, Runnable {

    public void commit() {
        if (mCommitted) throw new IllegalStateException("commit already called");
        if (FragmentManager.DEBUG) Log.v(TAG, "Commit: " + this);
        mCommitted = true;
        mManager.mActivity.mHandler.post(this);
        mManager.enqueueAction(this);
    }
    
    public void run() {
        if (FragmentManager.DEBUG) Log.v(TAG, "Run: " + this);
        
        Op op = mHead;
        while (op != null) {
            switch (op.cmd) {
@@ -286,6 +315,8 @@ final class BackStackEntry implements FragmentTransaction, Runnable {
                    if (mManager.mAdded != null) {
                        for (int i=0; i<mManager.mAdded.size(); i++) {
                            Fragment old = mManager.mAdded.get(i);
                            if (FragmentManager.DEBUG) Log.v(TAG,
                                    "OP_REPLACE: adding=" + f + " old=" + old);
                            if (old.mContainerId == f.mContainerId) {
                                if (op.removed == null) {
                                    op.removed = new ArrayList<Fragment>();
@@ -350,6 +381,8 @@ final class BackStackEntry implements FragmentTransaction, Runnable {
    }
    
    public void popFromBackStack() {
        if (FragmentManager.DEBUG) Log.v(TAG, "popFromBackStack: " + this);
        
        Op op = mTail;
        while (op != null) {
            switch (op.cmd) {
+61 −2
Original line number Diff line number Diff line
@@ -77,6 +77,10 @@ public class FragmentManager {
    static final boolean DEBUG = true;
    static final String TAG = "FragmentManager";
    
    ArrayList<Runnable> mPendingActions;
    Runnable[] mTmpActions;
    boolean mExecutingActions;
    
    ArrayList<Fragment> mActive;
    ArrayList<Fragment> mAdded;
    ArrayList<Integer> mAvailIndices;
@@ -91,6 +95,13 @@ public class FragmentManager {
    Bundle mStateBundle = null;
    SparseArray<Parcelable> mStateArray = null;
    
    Runnable mExecCommit = new Runnable() {
        @Override
        public void run() {
            execPendingActions();
        }
    };
    
    Animation loadAnimation(Fragment fragment, int transit, boolean enter,
            int transitionStyle) {
        Animation animObj = fragment.onCreateAnimation(transitionStyle, enter,
@@ -486,6 +497,52 @@ public class FragmentManager {
        return null;
    }
    
    public void enqueueAction(Runnable action) {
        synchronized (this) {
            if (mPendingActions == null) {
                mPendingActions = new ArrayList<Runnable>();
            }
            mPendingActions.add(action);
            if (mPendingActions.size() == 1) {
                mActivity.mHandler.removeCallbacks(mExecCommit);
                mActivity.mHandler.post(mExecCommit);
            }
        }
    }
    
    /**
     * Only call from main thread!
     */
    public void execPendingActions() {
        if (mExecutingActions) {
            throw new IllegalStateException("Recursive entry to execPendingActions");
        }
        
        while (true) {
            int numActions;
            
            synchronized (this) {
                if (mPendingActions == null || mPendingActions.size() == 0) {
                    return;
                }
                
                numActions = mPendingActions.size();
                if (mTmpActions == null || mTmpActions.length < numActions) {
                    mTmpActions = new Runnable[numActions];
                }
                mPendingActions.toArray(mTmpActions);
                mPendingActions.clear();
                mActivity.mHandler.removeCallbacks(mExecCommit);
            }
            
            mExecutingActions = true;
            for (int i=0; i<numActions; i++) {
                mTmpActions[i].run();
            }
            mExecutingActions = false;
        }
    }
    
    public void addBackStackState(BackStackEntry state) {
        if (mBackStack == null) {
            mBackStack = new ArrayList<BackStackEntry>();
@@ -503,8 +560,9 @@ public class FragmentManager {
                return false;
            }
            final BackStackEntry bss = mBackStack.remove(last);
            handler.post(new Runnable() {
            enqueueAction(new Runnable() {
                public void run() {
                    if (DEBUG) Log.v(TAG, "Popping back stack state: " + bss);
                    bss.popFromBackStack();
                    moveToState(mCurState, reverseTransit(bss.getTransition()),
                            bss.getTransitionStyle(), true);
@@ -526,9 +584,10 @@ public class FragmentManager {
            for (int i=mBackStack.size()-1; i>index; i--) {
                states.add(mBackStack.remove(i));
            }
            handler.post(new Runnable() {
            enqueueAction(new Runnable() {
                public void run() {
                    for (int i=0; i<states.size(); i++) {
                        if (DEBUG) Log.v(TAG, "Popping back stack state: " + states.get(i));
                        states.get(i).popFromBackStack();
                    }
                    moveToState(mCurState, true);
+97 −11
Original line number Diff line number Diff line
@@ -21,9 +21,11 @@ import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.widget.AdapterView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;

/**
 * An fragment that displays a list of items by binding to a data source such as
@@ -154,17 +156,28 @@ public class ListFragment extends Fragment {

    ListAdapter mAdapter;
    ListView mList;
    View mEmptyView;
    TextView mStandardEmptyView;
    View mProgressContainer;
    View mListContainer;
    boolean mSetEmptyView;
    boolean mListShown;

    public ListFragment() {
    }

    /**
     * Provide default implementation to return a simple list view.
     * Provide default implementation to return a simple list view.  Subclasses
     * can override to replace with their own layout.  If doing so, the
     * returned view hierarchy <em>must</em> have a ListView whose id
     * is {@link android.R.id.list android.R.id.list} and can optionally
     * have a sibling view id {@link android.R.id.empty android.R.id.empty}
     * that is to be shown when the list is empty.
     */
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        return inflater.inflate(com.android.internal.R.layout.list_content,
        return inflater.inflate(com.android.internal.R.layout.list_content_rich,
                container, false);
    }

@@ -246,6 +259,62 @@ public class ListFragment extends Fragment {
        return mList;
    }

    /**
     * The default content for a ListFragment has a TextView that can
     * be shown when the list is empty.  If you would like to have it
     * shown, call this method to supply the text it should use.
     */
    public void setEmptyText(CharSequence text) {
        ensureList();
        if (mStandardEmptyView == null) {
            throw new IllegalStateException("Can't be used with a custom content view");
        }
        if (!mSetEmptyView) {
            mSetEmptyView = true;
            mList.setEmptyView(mStandardEmptyView);
        }
    }
    
    /**
     * Control whether the list is being displayed.  You can make it not
     * displayed if you are waiting for the initial data to show in it.  During
     * this time an indeterminant progress indicator will be shown instead.
     * 
     * @param shown If true, the list view is shown; if false, the progress
     * indicator.  The initial value is true.
     * @param animate If true, an animation will be used to transition to the
     * new state.
     */
    public void setListShown(boolean shown, boolean animate) {
        ensureList();
        if (mProgressContainer == null) {
            throw new IllegalStateException("Can't be used with a custom content view");
        }
        if (mListShown == shown) {
            return;
        }
        mListShown = shown;
        if (shown) {
            if (animate) {
                mProgressContainer.startAnimation(AnimationUtils.loadAnimation(
                        getActivity(), android.R.anim.fade_out));
                mListContainer.startAnimation(AnimationUtils.loadAnimation(
                        getActivity(), android.R.anim.fade_in));
            }
            mProgressContainer.setVisibility(View.GONE);
            mListContainer.setVisibility(View.VISIBLE);
        } else {
            if (animate) {
                mProgressContainer.startAnimation(AnimationUtils.loadAnimation(
                        getActivity(), android.R.anim.fade_in));
                mListContainer.startAnimation(AnimationUtils.loadAnimation(
                        getActivity(), android.R.anim.fade_out));
            }
            mProgressContainer.setVisibility(View.VISIBLE);
            mListContainer.setVisibility(View.GONE);
        }
    }
    
    /**
     * Get the ListAdapter associated with this activity's ListView.
     */
@@ -261,16 +330,33 @@ public class ListFragment extends Fragment {
        if (root == null) {
            throw new IllegalStateException("Content view not yet created");
        }
        View emptyView = root.findViewById(com.android.internal.R.id.empty);
        mList = (ListView)root.findViewById(com.android.internal.R.id.list);
        if (root instanceof ListView) {
            mList = (ListView)root;
        } else {
            mStandardEmptyView = (TextView)root.findViewById(
                    com.android.internal.R.id.internalEmpty);
            if (mStandardEmptyView == null) {
                mEmptyView = root.findViewById(android.R.id.empty);
            }
            mProgressContainer = root.findViewById(com.android.internal.R.id.progressContainer);
            mListContainer = root.findViewById(com.android.internal.R.id.listContainer);
            View rawListView = root.findViewById(android.R.id.list);
            if (!(rawListView instanceof ListView)) {
                throw new RuntimeException(
                        "Content has view with id attribute 'android.R.id.list' "
                        + "that is not a ListView class");
            }
            mList = (ListView)rawListView;
            if (mList == null) {
                throw new RuntimeException(
                        "Your content must have a ListView whose id attribute is " +
                        "'android.R.id.list'");
            }
        if (emptyView != null) {
            mList.setEmptyView(emptyView);
            if (mEmptyView != null) {
                mList.setEmptyView(mEmptyView);
            }
        }
        mListShown = true;
        mList.setOnItemClickListener(mOnClickListener);
        if (mAdapter != null) {
            setListAdapter(mAdapter);
Loading