Android Fragment 组件学习
Fragment简介(google官方文档翻译)
一个Fragment是一个应用程序的用户界面或者行为的一小部分,可以放到一个Activity中来使用。FragmentManager负责其组织管理应用程序中的多个Fragment,它可用Activity.getFragmentManager()和Fragment.getFragmentManager()获得。
Fragment类可用于多种方式来实现各种效果。在其核心,它表示可以在一个较大的组件Activity运行的特定操作或接口。Fragment与它所在的Activity紧密相关,并且不能分开使用。虽然Fragment定义了自己的生命周期,它的生命周期仍然依赖于它所在的Activity:如果Activity 执行了onStop()方法,Activity的内部没有Fragment可以启动;当Activity被销毁,所有Fragment将被销毁。
Fragment的所有子类必须有一个公共的无参数的构造函数。在需要的时候,特别是在状态恢复时,初始化它的框架需要能够找到这个构造函数然后重新实例Fragment。如果无参数的构造函数不可用,运行时异常将发生在某些情况下状态中恢复。
Fragment的生命周期及Fragment和Activity的关系
Fragment 生命周期
Fragment和Activity生命周期对比
各个状态的含意
1.onAttached(Activity) —— 一旦Fragment与他的Activity建立联系就会被调用。
2.onCreate(Bundle)——被调用来执行初始创建Fragment的操作。
3.onCreateView(LayoutInflater,ViewGroup,Bundle) —— 返回或者创建于Fragment有关的视图层次。
4.onActivityCreated(Bundle) —— 当Fragment的Activity的onCreated()方法返回后此方法被调用.
5.onViewStateRestored(Bundle) —— 告诉Fragment它所有的视图层次的保存状态已经恢复了。
6.onStart()——使得Fragment对于用户可见(以包含它的Activity正在启动完成为基础)。
7.onResume()——使得Fragment与用户交互(建立在包含它的Activity正在恢复Resume完成)。
8.onPause()——Fragment不再与用户进行交互了,原因可能是:它的Activity已经暂停(onPause())了或者其他的Activity中的Fragment的操作正在修改它。
9.onStop()——Fragment对于用户不再可见,原因可能:它的Activity已经停止了(onStop())或者其他的Activity中的Fragment的操作正在修改它。
10.onDestroyView() ——允许Fragment清理和他显示有关的资源。
11.onDestroy()——做最后的清理工作的Fragment状态。
12.onDetach() ——当Fragment和它的Activity分离的时候调用这个方法。
Fragment和Activity对比
由于Activity是完全包含Fragment,所以Activity的生命周期要比Fragment的生命周期长。有这种包含关系的存在,Fragment相对于Activity来说要第一个层次,Fragment要和Activity的生命周期建立一种联系(onAttached(Activity),onDetach())。由于要在Fragment中要实现视图的动态加载和维护Activity中的回调的时序关系,Fragment增加了一些状态(onCreateView(LayoutInflater,ViewGroup,Bundle) ,onActivityCreated(Bundle) ,onDestroyView() )。Fragment的其他的状态与Activity都是对应的。
Fragment的使用方法
1.创建一个Fragment的子类,重写它的一些回调方法。通常至少重写这几个方法(onCreate(…),onCreateView(…),onPause())。另外,AndroidSDK中还有Fragment的一些子类,DialogFragment,ListFragment等,也可以创建这些类的子类。
2.在onCreateView(…)中添加界面布局。
public static class ExampleFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.example_fragment, container, false);
}
}
3.把Fragment添加到Activity
- 在Activity的layout文件中声明Fragment。
- 或者用编程的方式把Fragment添加到现存的ViewGroup中。
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
ExampleFragment fragment = new ExampleFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
更多细节可以查看googleAPI Guides
Fragment的使用实例
这个实例是一个SDK提供的NavigationDrawerActivity的代码,这部分代码很有意思,我在这里只选取了关于Fragment使用的部分。
创建Fragment子类重写了必要的方法,其中在onCreateView(…)中添加界面布局。
//NavigationDrawerFragment.java
public class NavigationDrawerFragment extends Fragment {
//...
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mDrawerListView = (ListView) inflater.inflate(R.layout.fragment_navigation_drawer, container, false);
mDrawerListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
selectItem(position);
}
});
mDrawerListView.setAdapter(new ArrayAdapter<String>(getActionBar().getThemedContext(),
android.R.layout.simple_list_item_activated_1, android.R.id.text1,
new String[] { getString(R.string.title_section1), getString(R.string.title_section2),
getString(R.string.title_section3),getString(R.string.title_section4),getString(R.string.title_section5),
getString(R.string.title_section6),getString(R.string.title_section7)}));
mDrawerListView.setItemChecked(mCurrentSelectedPosition, true);
return mDrawerListView;
}
//...
}
//fragment_navigation_drawer.xml
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#cccc"
android:choiceMode="singleChoice"
android:divider="@android:color/transparent"
android:dividerHeight="0dp"
tools:context="com.androidclub.connectdevice.NavigationDrawerFragment" />
添加界面布局
//MainActivity.java
public class MainActivity extends Activity implements NavigationDrawerFragment.NavigationDrawerCallbacks {
//...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mNavigationDrawerFragment = (NavigationDrawerFragment) getFragmentManager()
.findFragmentById(R.id.navigation_drawer);
mTitle = getTitle();
// Set up the drawer.
mNavigationDrawerFragment.setUp(R.id.navigation_drawer, (DrawerLayout) findViewById(R.id.drawer_layout));
}
public void onNavigationDrawerItemSelected(int position) {
// update the main content by replacing fragments
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.container, PlaceholderFragment.newInstance(position + 1))
.commit();
}
//..
}
<!-- A DrawerLayout is intended to be used as the top-level content view using match_parent for both width and height to consume the full space available. -->
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.androidclub.connectdevice.MainActivity" >
<!--
As the main content view, the view below consumes the entire
space available using match_parent in both dimensions.
-->
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!--
android:layout_gravity="start" tells DrawerLayout to treat
this as a sliding drawer on the left side for left-to-right
languages and on the right side for right-to-left languages.
If you're not building against API 17 or higher, use
android:layout_gravity="left" instead.
-->
<!--
The drawer is given a fixed width in dp and extends the full height of
the container.
-->
<fragment
android:id="@+id/navigation_drawer"
android:name="com.androidclub.connectdevice.NavigationDrawerFragment"
android:layout_width="@dimen/navigation_drawer_width"
android:layout_height="match_parent"
android:layout_gravity="start"
tools:layout="@layout/fragment_navigation_drawer" />
</android.support.v4.widget.DrawerLayout>