Fragment是Activity中的一部分,有自己的生命周期,但是受Activity的生命周期的影响。在onResume()之后,onPause()之前,可以单独操作每个Fragment,比如添加删除它们。在执行Fragment的事务时,可以将事务添加到一个栈中,这个栈被Activity管理,栈中每 一条都是fragment的一次事务,有了这个栈就可以反向的执行Fragment的事务,这样Fragment就可以支持返回键了。
如果Fragment被添加到了回退栈中,在删除或者是替换的时候它将会stop,如果没有添加,就是destroy销毁。
Fragment类型:DialogFragment、ListFragment、PreferenceFragment。DialogFragment:显示一个浮动的对话框。使用这个类创建对话框是使用Activity类对话框工具方法之外的另一个不错的选择,因为你可以把fragment对话框并入到由activity管理的fragments后台栈中,允许用户返回到一个已经摒弃的fragment。ListFragment:显示一个由适配器管理的条目列表(例如SimpleCursorAdapter),类似于ListActivity。并且提供了许多管理列表视图的函数,例如处理点击事件的onListItemClick()回调函PreferenceFragment:显示一个Preference对象的体系结构列表,类似于preferenceActivity。这在为应用程序创建“设置”activity时是很实用的。
你还可以使用FragmentManager打开一个FragmentTransaction来执行fragment的事务,比如添加或删除fragment。如果你添加了多个fragment,那么它们的显示顺序跟添加顺序一至(后显示的覆盖前面的)。如果你在执行的事务中有删除fragment的动作,而且没有调用addToBackStack(),那么当事务提交时,那些被删除的fragment就被销毁了。反之,那些fragment就不会被销毁,而是处于停止状态。当用户返回时,它们会被恢复。
密技:对于fragment事务,你可以应用动画。在commit()之前调用setTransition()就行。但是,调用commit()后,事务并不会马上执行。它会在activity的UI线程(其实就是主线程)中等待直到线程能执行的时候才执行(废话)。如果必要,你可以在UI线程中调用executePendingTransactions()方法来立即执行事务。但一般不需这样做,除非有其它线程在等待事务的执行。
警告:你只能在activity处于可保存状态的状态时,比如running中,onPause()方法和onStop()方法中提交事务,否则会引发异常。这是因为fragment的状态会丢失。如果要在可能丢失状态的情况下提交事务,请使用commitAllowingStateLoss()。
Fragment的生命周期:
Fragment的生命周期与Activity生命周期的比较:
Fragment 生命周期代码:
package com.kayak.fragmentstudy;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Toast;
public class FragmentTest extends Fragment implements OnClickListener,android.support.v4.app.FragmentManager.OnBackStackChangedListener{
public MainActivity2 activity;
/* (non-Javadoc)
* 当Fragment附加到父窗口Activity上时,也就是成为Activity一部分的时候
* 可以获取到父Activity的实例
* @see android.support.v4.app.Fragment#onAttach(android.app.Activity)
*/
@Override
public void onAttach(Activity activity) {
// TODO Auto-generated method stub
super.onAttach(activity);
this.activity = (MainActivity2) activity;
mCallBack = (onHeadlineSelectedListener) activity;
}
onHeadlineSelectedListener mCallBack;
private String mdString;
private Button bcs;
private String data;
//为了实现两个Fragment的交互,可以在fragment中定义一个接口,
//然后在这个接口中定义一个方法,在Fragment的onAffach()方法中调用这个接口
//中的方法,然后让Activity实现这个方法来完成Activity和Fragment之间
//的通信
public interface onHeadlineSelectedListener{
public void onArticleSelected(int position);
}
/* (non-Javadoc)
* 在创建fragment时系统会调用此方法。在实现代码中,你可以初始化想要在
* fragment中保持的那些必要组件(这里的组件是指除了view之外的东西,比如需要进行界面展示的关键数据),
* 当fragment处于暂停或者停止状态之后可重新启用它们。
* @see android.support.v4.app.Fragment#onCreate(android.os.Bundle)
*/
@Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
//初始化Fragment
super.onCreate(savedInstanceState);
if (getArguments() != null) {
data = getArguments().getString("data");
}
}
public static FragmentTest newInstance(int id) {
FragmentTest fragmentTest = new FragmentTest();
Bundle bundle = new Bundle();
bundle.putString("data",id+"");
fragmentTest.setArguments(bundle);
return fragmentTest;
}
/* (non-Javadoc)
* 在第一次为fragment绘制用户界面时系统会调用此方法。为fragment绘制用户界面,这个函数必须
* 要返回所绘出的fragment的根View。如果fragment没有用户界面可以返回空
* 注:如果你的fragment是从ListFragment中派生的,就不需要实现onCreateView()方法了,
* 因为默认的实现已经为你返回了ListView控件对象。
* onCreateView()参数中的container是存放fragment的layout的ViewGroup对象。
* @see android.support.v4.app.Fragment#onCreateView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle)
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreateView(inflater, container, savedInstanceState);
Bundle bundle = getArguments();
mdString = bundle.getString("md");
Toast.makeText(getActivity(), mdString, Toast.LENGTH_SHORT).show();
return inflater.inflate(R.layout.fragmenttest, null);
}
/* (non-Javadoc)
* 操作fragment的View
* @see android.support.v4.app.Fragment#onViewCreated(android.view.View, android.os.Bundle)
*/
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
bcs = (Button) view.findViewById(R.id.bcs);
bcs.setOnClickListener(this);
}
/* (non-Javadoc)
* 当父Activity和当前的Fragment的UI都完整创建完的时候被调用
* 初始化那些你需要你的父Activity或者是Fragment的UI已经被完整初始化才能初始化的元素
* @see android.support.v4.app.Fragment#onActivityCreated(android.os.Bundle)
*/
@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
}
/* (non-Javadoc)
* 开始
* @see android.support.v4.app.Fragment#onStart()
*/
@Override
public void onStart() {
// TODO Auto-generated method stub
super.onStart();
}
/* (non-Javadoc)
* 重新开始
* @see android.support.v4.app.Fragment#onResume()
*/
@Override
public void onResume() {
// TODO Auto-generated method stub
super.onResume();
}
/* (non-Javadoc)
* 清除所有资源包括要结束的线程,关闭数据库连接等等
* @see android.support.v4.app.Fragment#onDestroy()
*/
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
}
/* (non-Javadoc)
* 当你的Fragment的UI被分离的时候、清除所有和视图有关的资源
* @see android.support.v4.app.Fragment#onDestroyView()
*/
@Override
public void onDestroyView() {
// TODO Auto-generated method stub
super.onDestroyView();
}
/* (non-Javadoc)
* 当你的Fragment从父activity身上分离的时候
* @see android.support.v4.app.Fragment#onDetach()
*/
@Override
public void onDetach() {
// TODO Auto-generated method stub
super.onDetach();
}
/* (non-Javadoc)
* 系统回调用该函数作为用户离开fragment的第一个预兆
* (尽管这并不总意味着fragment被销毁)。在当前用户会话结束之前
* ,通常要在这里提交任何应该持久化的变化(因为用户可能不再返回)。
* @see android.support.v4.app.Fragment#onPause()
*/
@Override
public void onPause() {
// TODO Auto-generated method stub
super.onPause();
}
@Override
public void onStop() {
// TODO Auto-generated method stub
super.onStop();
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
public void sc() {
bcs.setText("nishiwode");
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bcs:
SpannableStringBuilder style=new SpannableStringBuilder("CS");
style.setSpan(new ForegroundColorSpan(Color.RED),0,1,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
bcs.setText(style);
mCallBack.onArticleSelected(1);
activity.chReplaceFrag(new FragmentTestSecond() , "", true);
FragmentManager vFragmentManager = getFragmentManager();
//获取App中Fragment管理器 API最低是11
//android.app.FragmentManager aFragmentManager = getFragmentManager();
FragmentTransaction vTransaction = vFragmentManager.beginTransaction();
FragmentTestSecond fragmentTest = new FragmentTestSecond();
vTransaction.replace(R.id.flt, fragmentTest);
//vFragmentManager.popBackStack();
//设置可以点击返回键、在后退栈中保存被代替的fragment的状态。
//如果你向事务添加了多个动作,比如多次调用了add(),remove()等之后又调用了addToBackStack()方法,那么所有的在commit()之前调用的方法都被作为一个事务。当用户按返回键时,所有的动作都被反向执行(事务回溯)。
vTransaction.addToBackStack(null);
//添加返回键的监听
vFragmentManager.addOnBackStackChangedListener(this);
//应用动画
vTransaction.setTransition(1);
//提交事务
//vTransaction.commit();
//提交可以丢失的提交
//vTransaction.commitAllowingStateLoss();
break;
default:
break;
}
}
//点击返回键的监听
@Override
public void onBackStackChanged() {
// TODO Auto-generated method stub
}
}
Fragment 生命周期测试例子:
1.切换到Fragment是调用的6个方法: onAttach、onCreate、onCreateView、onActivityCreated、onStart、onResume
2.屏幕灭掉Fragment调用的3个方法:onPause、onSaveInstanceState、onStop(调用生命周期的2个方法)
3.屏幕解锁Fragment调用的2个方法:onStart、onResume
4.切换到其他Fragment调用的3个方法:onPause、onStop、onDestroyView
5.切换回本身的Fragment调用的4个方法:onCreateView、onActivityCreated、onStart、onResume
6.回到桌面调用的3个方法:onPause、onSaveInstanceState、onStop(调用生命周期的2个方法)
7.回到应用:onStart、onResume
8.退出应用: onPause、onStop、onDestroyView、onDestroy、onDetach
FragmentManager整理:
1.findFragmentById()或findFragmentByTag(),获取activity中已存在的fragment
2.将fragment从后台堆栈中弹出, 使用 popBackStack() (模拟用户按下BACK 命令).
3.通过addOnBackStackChangedListerner()注册一个侦听器以监视后退栈的变化
FragmentTransaction整理:每一个事务都是要同时执行的一套变化
1.addToBackStack() 添加回滚,这里回滚的是一套变化
2.commit 并不是马上执行,可以从你的UI线程(主线程)调用 vFragmentManager.executePendingTransactions();来立即执行, 需要在用户离开Activity之前执行事务。这 是因为如果activity需要被恢复, 提交之后的状态可能会丢失. 对于你觉得可以丢失提交的状况, 使用 commitAllowingStateLoss().
1.add (多层)是把fragment 添加到container容器
2.replace (单层)是先remove掉相同id的所有fragment,然后在add当前的这个fragment。
3.一般是使用FrameLayout来做容器的
4.使用hide()方法只是隐藏了fragment的view并没有将view从viewtree中删除,随后可用show()方法将view设置为显示
Fragment与Activity的交互,通过接口回调的方式实现
package com.example.jh;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.widget.Toast;
import com.example.jh.FragmentTest.onHeadlineSelectedListener;
public class MainActivity extends FragmentActivity implements onHeadlineSelectedListener{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.fl, new FragmentTest());
transaction.commit();
}
@Override
public void onArticleSelected(int position) {
//这里的position就是FragmentTest传过来的数据
//可以用来交互
int num = position;
Toast.makeText(this, ""+num, 0).show();
}
}
package com.example.jh;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class FragmentTest extends Fragment{
onHeadlineSelectedListener mhsl;
@Override
public void onAttach(Activity activity) {
// TODO Auto-generated method stub
super.onAttach(activity);
mhsl = (onHeadlineSelectedListener) activity;
}
@Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
//这里可以传递数据到activity
mhsl.onArticleSelected(10);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View view = inflater.inflate(R.layout.fragment_test, null);
return view;
}
//为了实现两个Fragment的交互,可以在fragment中定义一个接口,
//然后在这个接口中定义一个方法,在Fragment的onAttach()方法中调用这个接口
//中的方法,然后让Activity实现这个方法来完成Activity和Fragment之间
//的通信
public interface onHeadlineSelectedListener{
public void onArticleSelected(int position);
}
}