Android - Fragments

Fragment is like a portion of user interface. We can use multiple Fragments in one Activity, or reuse one fragment in multiple activities.

A fragment must be embeded in an activity and its lifecycle is directly affected by its host. For example, if the activity is paused/destoryed, all fragments in this activity will be paused/destoryed. However, when the activity is running (assumed), we can manipulate (add or replace) the containing fragments.

When we perform FragmentTransaction, we can add it to a back stack that is managed by system. So the back stack will record the transaction and allows user to navigate backwards by pressing the back button.

There are two methods to add a fragment into a ViewGroup or layout.

  1. declaring the fragment tag in the activity’s layout file
  2. dynamically using fragmentTransaction to add it to an existing ViewGroup

1. Creating a Fragment

To create a fragment, we should extend a Fragment Class, like Fragment, ListFragment, DialogFragment, PreferenceFragment and so on.
DialogFragment: Displays a floating dialog.

ListFragment: Displays a list of items that are managed by an adapter (such as a SimpleCursorAdapter), similar to ListActivity.

PreferenceFragment: Displays a hierarchy of Preference objects as a list, similar to PreferenceActivity

The life cycle of Fragments:
OnAttach() - OnCreate() - OnCreateView() - OnActivityView() - OnActivityCreated() - OnStart() - OnResume() - OnPause() - OnStop() - OnDestroyView() - OnDestroy() - OnDetach()

This is similar to activity, but get more steps.
Some fundamental functions:
OnCreate(): The system will call this when creating fragment. So we should initialize essential components (some views) of fragment.

OnCreateView(): The system calls this when it’s time to draw UI for the first time. So here we must return a View from this method. Return a view object (layout)
To provide a layout for a fragment, you must implement the onCreateView() callback method, which the Android system calls when it’s time for the fragment to draw its layout. But If your fragment is a subclass of ListFragment, the default implementation returns a ListView from onCreateView(), so you don’t need to implement it.

public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

        return inflater.inflate(R.layout.feed, container, false);
// The "container" is the activity's layout in which your fragment is going to be inserted.
// The "Bundle" provides data about the previous instance of the fragment, if the fragment is being resumed 
// A boolean indicating whether the inflated layout should be attached to the 

    }

OnPause(): When user leaving the fragment, we should commit or save some important changes in this function.


2. Adding a fragment to an activity

Method 1: Declare the fragment inside the activity’s layout file.
For example, give a fragment’s class to its name attribute

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <fragment android:name="com.example.news.ArticleListFragment"
            android:id="@+id/list"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="match_parent" />
    <fragment android:name="com.example.news.ArticleReaderFragment"
            android:id="@+id/viewer"
            android:layout_weight="2"
            android:layout_width="0dp"
            android:layout_height="match_parent" />
</LinearLayout>

When the system creates this activity layout, it instantiates each fragment specified in the layout and calls the onCreateView() method for each one, to retrieve each fragment’s layout. The system inserts the View returned by the fragment directly in place of the fragment tag.

a unique identifier that the system can use to restore the fragment is recommended. Supply the id or tag, so that we can retrieve the fragment by “FM.findFragmentById()” or “FM.findFragmentByTag()” (FM is fragmentManager)

Method 2: programmatically add the fragment to an existing ViewGroup.

You simply need to specify a ViewGroup in which to place the fragment. And use FragmentTransaction to dynamically add or remove fragments:
For example:

FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

ExampleFragment fragment = new ExampleFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();

Note: Once you’ve made your changes with FragmentTransaction, you must call commit() for the changes to take effect.

Note: For FragmentManager, we can register a listener for changes to the back stack with addOnBackStackChangedListener()

For each FragmentTransaction, before commit(), we can use ft.addToBackStack(null) funtion to add this action into backStack, So when user hit back button, it can be navigated to previous fragment. (back stack does not track the changes about fragment by default). So if you do not call addToBackStack() when you perform a transaction that removes a fragment, then that fragment is destroyed when the transaction is committed and the user cannot navigate back to it.

Note: Calling commit() does not perform the transaction immediately. Rather, it schedules it to run on the activity’s UI thread (the “main” thread) as soon as the thread is able to do so. If necessary, however, you may call executePendingTransactions() from your UI thread to immediately execute transactions submitted by commit(). Doing so is usually not necessary unless the transaction is a dependency for jobs in other threads.


3. Communicating with the Activity

Specifically, the fragment can access the Activity instance with getActivity() and easily perform tasks such as find a view in the activity layout:

View listView = getActivity().findViewById(R.id.list);

Likewise, your activity can call methods in the fragment by acquiring a reference to the Fragment from FragmentManager, using findFragmentById() or findFragmentByTag()


More complex cases like a fragment sharing events with the activity.

A good way to do that is to define a callback interface inside the fragment and require that the host activity implement it. (using interface callback)


4. Handling the Fragment Lifecycle

lifecycle of Fragment
Note: There are two cases that can result in Stop. Firstly, the fragment is non visible. Secondly, the fragment has been removed from activity but added to the back stack.

Also like an activity, you can retain the state of a fragment using a Bundle, in case the activity’s process is killed and you need to restore the fragment state when the activity is recreated. You can save the state during the fragment’s onSaveInstanceState() callback and restore it during either onCreate(), onCreateView(), or onActivityCreated().

Caution: If you need a Context object within your Fragment, you can call getActivity(). However, be careful to call getActivity() only when the fragment is attached to an activity. When the fragment is not yet attached, or was detached during the end of its lifecycle, getActivity() will return null.


Additional callback methods

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值