您的位置:首页 > 移动开发 > Android开发

【Android学习笔记】Activity的小弟--Fragment以及异步加载数据的Loader

2015-11-05 18:29 579 查看

一、What is a fragment?

首先,fragment总是被嵌入到一个activity中,你可以把它看做是activity中的一个模块,也是用来呈现数据的,但它不需要在manifest中配置,因此可以看做一个轻量级的activity。它有着自己的生命周期,但又依赖与attach的activity。Fragment的出现是为了解决大屏适配的问题,但现在你可以利用fragment来实现更多的功能,比如微信的主界面、QQ的主界面(fragment+framelayout+其他)等。



二、How to create and use it ?

通常的步骤如下:
1.编写xml布局文件(类似activity对应的xml)
2.继承Fragment(或者DialogFragment、ListFragment),并在生命周期方法的onCreateView方法进行inflate
3.在activity的xml中使用,通过<fragment android:name="完整的包名">
4.在attach的activity中通过FragmentManager来findFragmentById或者findFragmentByTag(没有界面的fragment),然后通过FragmentTransaction来进行remove、replace、add等动态的操作,最后commit

三、Lifecycle

Fragment的生命周期往往依赖与attach的activity,比如activity如果resumed则fragment resumed,activity如果paused,则fragment paused,如果activity stopped 则 fragment stopped
如图所示



至少应该实现如下的几个回调方法:

onCreate()

在创建fragment时系统会调用此方法。在实现代码中,你可以初始化想要在fragment中保持的那些必要组件,当fragment处于暂停或者停止状态之后可重新启用它们。
onCreateView()

在第一次为fragment绘制用户界面时系统会调用此方法。为fragment绘制用户界面,这个函数必须要返回所绘出的fragment的根View。如果fragment没有用户界面可以返回空。
onPause()

系统回调用该函数作为用户离开fragment的第一个预兆(尽管这并不总意味着fragment被销毁)。在当前用户会话结束之前,通常要在这里提交任何应该持久化的变化(因为用户可能不再返回)。
大部分应用程序都应该至少为每个fragment实现这三个方法,但是还有许多其他用以操纵fragment生命周期中各个阶段的回调函数。


四、Communicating

1.Fragment访问Activity,通过getActivity()或者采用回调接口的方式(fragment内部定义个接口,activity实现它)
2.Activity访问Fragment,通过FragmentManager
3.Fragment或者Activity访问持久化的数据参看文章http://item.congci.com/item/android-loaders-yibu-jiazai-shuju

五、官方Doc中的典型例子

具体的场景一看代码就明白了,主要是横屏显示(左边title右边detail)和竖屏显示的处理逻辑
public static class TitlesFragment extends ListFragment {
boolean mDualPane;
int mCurCheckPosition = 0;

@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);

// Populate list with our static array of titles.
setListAdapter(new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_activated_1, Shakespeare.TITLES));

// Check to see if we have a frame in which to embed the details
// fragment directly in the containing UI.
View detailsFrame = getActivity().findViewById(R.id.details);
mDualPane = detailsFrame != null && detailsFrame.getVisibility() == View.VISIBLE;

if (savedInstanceState != null) {
// Restore last state for checked position.
mCurCheckPosition = savedInstanceState.getInt("curChoice", 0);
}

if (mDualPane) {
// In dual-pane mode, the list view highlights the selected item.
getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
// Make sure our UI is in the correct state.
showDetails(mCurCheckPosition);
}
}

@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("curChoice", mCurCheckPosition);
}

@Override
public void onListItemClick(ListView l, View v, int position, long id) {
showDetails(position);
}

/**
* Helper function to show the details of a selected item, either by
* displaying a fragment in-place in the current UI, or starting a
* whole new activity in which it is displayed.
*/
void showDetails(int index) {
mCurCheckPosition = index;

if (mDualPane) {
// We can display everything in-place with fragments, so update
// the list to highlight the selected item and show the data.
getListView().setItemChecked(index, true);

// Check what fragment is currently shown, replace if needed.
DetailsFragment details = (DetailsFragment)
getFragmentManager().findFragmentById(R.id.details);
if (details == null || details.getShownIndex() != index) {
// Make new fragment to show this selection.
details = DetailsFragment.newInstance(index);

// Execute a transaction, replacing any existing fragment
// with this one inside the frame.
FragmentTransaction ft = getFragmentManager().beginTransaction();
if (index == 0) {
ft.replace(R.id.details, details);
} else {
ft.replace(R.id.a_item, details);
}
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.commit();
}

} else {
// Otherwise we need to launch a new activity to display
// the dialog fragment with selected text.
Intent intent = new Intent();
intent.setClass(getActivity(), DetailsActivity.class);
intent.putExtra("index", index);
startActivity(intent);
}
}
}


public static class DetailsFragment extends Fragment {
/**
* Create a new instance of DetailsFragment, initialized to
* show the text at 'index'.
*/
public static DetailsFragment newInstance(int index) {
DetailsFragment f = new DetailsFragment();

// Supply index input as an argument.
Bundle args = new Bundle();
args.putInt("index", index);
f.setArguments(args);

return f;
}

public int getShownIndex() {
return getArguments().getInt("index", 0);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (container == null) {
// We have different layouts, and in one of them this
// fragment's containing frame doesn't exist.  The fragment
// may still be created from its saved state, but there is
// no reason to try to create its view hierarchy because it
// won't be displayed.  Note this is not needed -- we could
// just run the code below, where we would create and return
// the view hierarchy; it would just never be used.
return null;
}

ScrollView scroller = new ScrollView(getActivity());
TextView text = new TextView(getActivity());
int padding = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
4, getActivity().getResources().getDisplayMetrics());
text.setPadding(padding, padding, padding, padding);
scroller.addView(text);
text.setText(Shakespeare.DIALOGUE[getShownIndex()]);
return scroller;
}
}

public static class DetailsActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

if (getResources().getConfiguration().orientation
== Configuration.ORIENTATION_LANDSCAPE) {
// If the screen is now in landscape mode, we can show the
// dialog in-line with the list so we don't need this activity.
finish();
return;
}

if (savedInstanceState == null) {
// During initial setup, plug in the details fragment.
DetailsFragment details = new DetailsFragment();
details.setArguments(getIntent().getExtras());
getFragmentManager().beginTransaction().add(android.R.id.content, details).commit();
}
}
}


六、参考文献
1.官方文档
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android fragment