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

Commit 2dedce6e authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Introducing Fragment.

Basic implementation of an API for organizing a single activity into separate,
discrete pieces.  Currently supports adding and removing fragments, and
performing basic lifecycle callbacks on them.

Change-Id: I6ea8e6bdb04d93f8105c2e983fe9b6532422de34
parent 2df4c76b
Loading
Loading
Loading
Loading
+305 −0
Original line number Diff line number Diff line
@@ -20304,6 +20304,17 @@
<parameter name="view" type="android.view.View">
</parameter>
</method>
<method name="openFragmentTransaction"
 return="android.app.FragmentTransaction"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="openOptionsMenu"
 return="void"
 abstract="false"
@@ -24658,6 +24669,300 @@
</parameter>
</method>
</class>
<class name="Fragment"
 extends="java.lang.Object"
 abstract="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<implements name="android.content.ComponentCallbacks">
</implements>
<constructor name="Fragment"
 type="android.app.Fragment"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</constructor>
<constructor name="Fragment"
 type="android.app.Fragment"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="name" type="java.lang.String">
</parameter>
</constructor>
<method name="getActivity"
 return="android.app.Activity"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="getName"
 return="java.lang.String"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="onAttach"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="activity" type="android.app.Activity">
</parameter>
</method>
<method name="onConfigurationChanged"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="newConfig" type="android.content.res.Configuration">
</parameter>
</method>
<method name="onCreate"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="savedInstanceState" type="android.os.Bundle">
</parameter>
</method>
<method name="onCreateView"
 return="android.view.View"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="inflater" type="android.view.LayoutInflater">
</parameter>
<parameter name="container" type="android.view.ViewGroup">
</parameter>
</method>
<method name="onDestroy"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="onDetach"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="onLowMemory"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="onPause"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="onRestart"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="onRestoreInstanceState"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="savedInstanceState" type="android.os.Bundle">
</parameter>
</method>
<method name="onResume"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="onRetainNonConfigurationInstance"
 return="java.lang.Object"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="onSaveInstanceState"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="outState" type="android.os.Bundle">
</parameter>
</method>
<method name="onStart"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="onStop"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
</class>
<interface name="FragmentTransaction"
 abstract="true"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<method name="add"
 return="android.app.FragmentTransaction"
 abstract="true"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="fragment" type="android.app.Fragment">
</parameter>
<parameter name="containerViewId" type="int">
</parameter>
</method>
<method name="add"
 return="android.app.FragmentTransaction"
 abstract="true"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="fragment" type="android.app.Fragment">
</parameter>
<parameter name="name" type="java.lang.String">
</parameter>
<parameter name="containerViewId" type="int">
</parameter>
</method>
<method name="commit"
 return="void"
 abstract="true"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="remove"
 return="android.app.FragmentTransaction"
 abstract="true"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="fragment" type="android.app.Fragment">
</parameter>
</method>
</interface>
<class name="Instrumentation"
 extends="java.lang.Object"
 abstract="false"
+86 −0
Original line number Diff line number Diff line
@@ -650,6 +650,65 @@ public class Activity extends ContextThemeWrapper
    private CharSequence mTitle;
    private int mTitleColor = 0;

    final FragmentManager mFragments = new FragmentManager();
    
    private final class FragmentTransactionImpl implements FragmentTransaction {
        ArrayList<Fragment> mAdded;
        ArrayList<Fragment> mRemoved;
        
        public FragmentTransaction add(Fragment fragment, int containerViewId) {
            return add(fragment, null, containerViewId);
        }

        public FragmentTransaction add(Fragment fragment, String name, int containerViewId) {
            if (fragment.mActivity != null) {
                throw new IllegalStateException("Fragment already added: " + fragment);
            }
            if (name != null) {
                fragment.mName = name;
            }
            if (mRemoved != null) {
                mRemoved.remove(fragment);
            }
            if (mAdded == null) {
                mAdded = new ArrayList<Fragment>();
            }
            fragment.mContainerId = containerViewId;
            mAdded.add(fragment);
            return this;
        }

        public FragmentTransaction remove(Fragment fragment) {
            if (fragment.mActivity == null) {
                throw new IllegalStateException("Fragment not added: " + fragment);
            }
            if (mAdded != null) {
                mAdded.remove(fragment);
            }
            if (mRemoved == null) {
                mRemoved = new ArrayList<Fragment>();
            }
            mRemoved.add(fragment);
            return this;
        }

        public void commit() {
            if (mRemoved != null) {
                for (int i=mRemoved.size()-1; i>=0; i--) {
                    mFragments.removeFragment(mRemoved.get(i));
                }
            }
            if (mAdded != null) {
                for (int i=mAdded.size()-1; i>=0; i--) {
                    mFragments.addFragment(mAdded.get(i));
                }
            }
            if (mFragments != null) {
                mFragments.moveToState(mFragments.mCurState);
            }
        }
    }
    
    private static final class ManagedCursor {
        ManagedCursor(Cursor cursor) {
            mCursor = cursor;
@@ -1463,6 +1522,14 @@ public class Activity extends ContextThemeWrapper
        mCalled = true;
    }
    
    /**
     * Start a series of edit operations on the Fragments associated with
     * this activity.
     */
    public FragmentTransaction openFragmentTransaction() {
        return new FragmentTransactionImpl();
    }
    
    /**
     * Wrapper around
     * {@link ContentResolver#query(android.net.Uri , String[], String, String[], String)}
@@ -3743,6 +3810,8 @@ public class Activity extends ContextThemeWrapper
            Configuration config) {
        attachBaseContext(context);

        mFragments.attachActivity(this);
        
        mWindow = PolicyManager.makeNewWindow(this);
        mWindow.setCallback(this);
        if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
@@ -3776,6 +3845,11 @@ public class Activity extends ContextThemeWrapper
        return mParent != null ? mParent.getActivityToken() : mToken;
    }

    final void performCreate(Bundle icicle) {
        onCreate(icicle);
        mFragments.dispatchCreate(icicle);
    }
    
    final void performStart() {
        mCalled = false;
        mInstrumentation.callActivityOnStart(this);
@@ -3784,6 +3858,7 @@ public class Activity extends ContextThemeWrapper
                "Activity " + mComponent.toShortString() +
                " did not call through to super.onStart()");
        }
        mFragments.dispatchStart();
    }
    
    final void performRestart() {
@@ -3830,6 +3905,9 @@ public class Activity extends ContextThemeWrapper
        // Now really resume, and install the current status bar and menu.
        mResumed = true;
        mCalled = false;
        
        mFragments.dispatchResume();
        
        onPostResume();
        if (!mCalled) {
            throw new SuperNotCalledException(
@@ -3839,6 +3917,7 @@ public class Activity extends ContextThemeWrapper
    }

    final void performPause() {
        mFragments.dispatchPause();
        onPause();
    }
    
@@ -3853,6 +3932,8 @@ public class Activity extends ContextThemeWrapper
                mWindow.closeAllPanels();
            }

            mFragments.dispatchStop();
            
            mCalled = false;
            mInstrumentation.callActivityOnStop(this);
            if (!mCalled) {
@@ -3877,6 +3958,11 @@ public class Activity extends ContextThemeWrapper
        mResumed = false;
    }

    final void performDestroy() {
        mFragments.dispatchDestroy();
        onDestroy();
    }
    
    final boolean isResumed() {
        return mResumed;
    }
+1 −1
Original line number Diff line number Diff line
@@ -3643,7 +3643,7 @@ public final class ActivityThread {
            }
            try {
                r.activity.mCalled = false;
                r.activity.onDestroy();
                mInstrumentation.callActivityOnDestroy(r.activity);
                if (!r.activity.mCalled) {
                    throw new SuperNotCalledException(
                        "Activity " + safeToComponentShortString(r.intent) +
+119 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.app;

import android.content.ComponentCallbacks;
import android.content.res.Configuration;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * A Fragment is a piece of an application's user interface or behavior
 * that can be placed in an {@link Activity}.
 */
public class Fragment implements ComponentCallbacks {
    static final int INITIALIZING = 0;  // Not yet created.
    static final int CREATED = 1;       // Created.
    static final int STARTED = 2;       // Created and started, not resumed.
    static final int RESUMED = 3;       // Created started and resumed.
    
    String mName;
    
    int mState = INITIALIZING;
    Activity mActivity;
    
    boolean mCalled;
    int mContainerId;
    
    ViewGroup mContainer;
    View mView;
    
    public Fragment() {
    }
    
    public Fragment(String name) {
        mName = name;
    }
    
    public String getName() {
        return mName;
    }
    
    public Activity getActivity() {
        return mActivity;
    }
    
    public void onAttach(Activity activity) {
        mCalled = true;
    }
    
    public void onCreate(Bundle savedInstanceState) {
        mCalled = true;
    }
    
    public View onCreateView(LayoutInflater inflater, ViewGroup container) {
        return null;
    }
    
    public void onRestoreInstanceState(Bundle savedInstanceState) {
    }
    
    public void onStart() {
        mCalled = true;
    }
    
    public void onRestart() {
        mCalled = true;
    }
    
    public void onResume() {
        mCalled = true;
    }
    
    public void onSaveInstanceState(Bundle outState) {
    }
    
    public void onConfigurationChanged(Configuration newConfig) {
        mCalled = true;
    }
    
    public Object onRetainNonConfigurationInstance() {
        return null;
    }
    
    public void onPause() {
        mCalled = true;
    }
    
    public void onStop() {
        mCalled = true;
    }
    
    public void onLowMemory() {
        mCalled = true;
    }
    
    public void onDestroy() {
        mCalled = true;
    }
    
    public void onDetach() {
        mCalled = true;
    }
}
+183 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.app;

import android.os.Bundle;
import android.view.ViewGroup;

import java.util.ArrayList;

/**
 * Container for fragments associated with an activity.
 */
class FragmentManager {
    final ArrayList<Fragment> mFragments = new ArrayList<Fragment>();
    
    int mCurState = Fragment.INITIALIZING;
    Activity mActivity;
    
    void moveToState(Fragment f, int newState) {
        if (f.mState < newState) {
            switch (f.mState) {
                case Fragment.INITIALIZING:
                    f.mActivity = mActivity;
                    f.mCalled = false;
                    f.onAttach(mActivity);
                    if (!f.mCalled) {
                        throw new SuperNotCalledException("Fragment " + f
                                + " did not call through to super.onAttach()");
                    }
                    f.mCalled = false;
                    f.onCreate(null);
                    if (!f.mCalled) {
                        throw new SuperNotCalledException("Fragment " + f
                                + " did not call through to super.onCreate()");
                    }
                    
                    ViewGroup container = null;
                    if (f.mContainerId != 0) {
                        container = (ViewGroup)mActivity.findViewById(f.mContainerId);
                        if (container == null) {
                            throw new IllegalArgumentException("New view found for id 0x"
                                    + Integer.toHexString(f.mContainerId)
                                    + " for fragment " + f);
                        }
                    }
                    f.mContainer = container;
                    f.mView = f.onCreateView(mActivity.getLayoutInflater(), container);
                    if (container != null && f.mView != null) {
                        container.addView(f.mView);
                    }
                    
                case Fragment.CREATED:
                    if (newState > Fragment.CREATED) {
                        f.mCalled = false;
                        f.onStart();
                        if (!f.mCalled) {
                            throw new SuperNotCalledException("Fragment " + f
                                    + " did not call through to super.onStart()");
                        }
                    }
                case Fragment.STARTED:
                    if (newState > Fragment.STARTED) {
                        f.mCalled = false;
                        f.onResume();
                        if (!f.mCalled) {
                            throw new SuperNotCalledException("Fragment " + f
                                    + " did not call through to super.onResume()");
                        }
                    }
            }
        } else if (f.mState > newState) {
            switch (f.mState) {
                case Fragment.RESUMED:
                    if (newState < Fragment.RESUMED) {
                        f.mCalled = false;
                        f.onPause();
                        if (!f.mCalled) {
                            throw new SuperNotCalledException("Fragment " + f
                                    + " did not call through to super.onPause()");
                        }
                    }
                case Fragment.STARTED:
                    if (newState < Fragment.STARTED) {
                        f.mCalled = false;
                        f.onStop();
                        if (!f.mCalled) {
                            throw new SuperNotCalledException("Fragment " + f
                                    + " did not call through to super.onStop()");
                        }
                    }
                case Fragment.CREATED:
                    if (newState < Fragment.CREATED) {
                        if (f.mContainer != null && f.mView != null) {
                            f.mContainer.removeView(f.mView);
                        }
                        f.mContainer = null;
                        f.mView = null;
                        
                        f.mCalled = false;
                        f.onDestroy();
                        if (!f.mCalled) {
                            throw new SuperNotCalledException("Fragment " + f
                                    + " did not call through to super.onDestroy()");
                        }
                        f.mCalled = false;
                        f.onDetach();
                        if (!f.mCalled) {
                            throw new SuperNotCalledException("Fragment " + f
                                    + " did not call through to super.onDetach()");
                        }
                        f.mActivity = null;
                    }
            }
        }
        
        f.mState = newState;
    }
    
    void moveToState(int newState) {
        if (mActivity == null && newState != Fragment.INITIALIZING) {
            throw new IllegalStateException("No activity");
        }
        
        mCurState = newState;
        for (int i=0; i<mFragments.size(); i++) {
            Fragment f = mFragments.get(i);
            moveToState(f, newState);
        }
    }
    
    public void addFragment(Fragment fragment) {
        mFragments.add(fragment);
    }
    
    public void removeFragment(Fragment fragment) {
        mFragments.remove(fragment);
        moveToState(fragment, Fragment.INITIALIZING);
    }
    
    public void attachActivity(Activity activity) {
        if (mActivity != null) throw new IllegalStateException();
        mActivity = activity;
    }
    
    public void dispatchCreate(Bundle state) {
        moveToState(Fragment.CREATED);
    }
    
    public void dispatchStart() {
        moveToState(Fragment.STARTED);
    }
    
    public void dispatchResume() {
        moveToState(Fragment.RESUMED);
    }
    
    public void dispatchPause() {
        moveToState(Fragment.STARTED);
    }
    
    public void dispatchStop() {
        moveToState(Fragment.CREATED);
    }
    
    public void dispatchDestroy() {
        moveToState(Fragment.INITIALIZING);
        mActivity = null;
    }
}
Loading