Activity和Fragment
今天主要的任务是切换Activity中不同的Fragment:在一个Activity中包含4个Fragment,根据进度条的值来确定要切换到对应的Fragment中,遇到的几个问题如下。
1. Fragment间调用show和hide方法时调用onStart()和onResume()方法时没有调用。
描述:在Activity包含4个Fragment,在任务进行时调用每个Activity,但是在返回时需要对Fragment进行隐藏和显示,调用show()和hide()方法。想在Fragment可见状态下显示新选定的数据,调用onStart()和onResume()时发现,只有在Activity切换到Fragment第一次时调用,第二次可见时并不调用。
private void switchFragment(Fragment toFragment) {
FragmentTransaction beginTransaction = fragmentManager.beginTransaction();
hideCurrentFragment(beginTransaction);
if (!toFragment.isAdded()) {
beginTransaction.add(R.id.fl_content_load_car_digital_lock, toFragment);
} else {
beginTransaction.show(toFragment);
}
currentFragment = toFragment;
beginTransaction.addToBackStack(null);
beginTransaction.commit();
}
解决方案:
当Fragment 从隐藏切换至显示的时候,不会调用onResume()和onStart(),Fragment 的onResume()和onStart()是Fragment 和它的宿主在切换时才会调用的,而Fragment 之前切换时,不会调用onResume()方法,Fragment 从隐藏切换至显示,会调用onHiddenChanged(boolean hidden)方法。
public void onHiddenChanged(boolean hidden) {
// TODO Auto-generated method stub
super.onHiddenChanged(hidden);
if (hidden) {// 不在最前端界面显示
} else {// 重新显示到最前端中
//可在此处完成界面可视需要显示的数据
}
}
2. Fragment的生命周期。
Fragment必须是依存与Activity而存在的,因此Activity的生命周期会直接影响到Fragment的生命周期。二者的生命周期关系如下:
- onAttach(Activity):执行该方法时,Fragment与Activity已经完成绑定,该方法有一个Activity类型的参数,代表绑定的Activity,这时候你可以执行诸如mActivity = activity的操作。
- onCreate():初始化Fragment。可通过参数savedInstanceState获取之前保存的值。
- onCreateView(LayoutInflater, ViewGroup,Bundle):初始化Fragment的布局。加载布局和findViewById的操作通常在此函数内完成,但是不建议执行耗时的操作,比如读取数据库数据列表。
- onActivityCreated(Bundle):执行该方法时,与Fragment绑定的Activity的onCreate方法已经执行完成并返回,在该方法内可以进行与Activity交互的UI操作,所以在该方法之前Activity的onCreate方法并未执行完成,如果提前进行交互操作,会引发空指针异常。
- onStart():执行该方法时,Fragment由不可见变为可见状态。
- onResume():执行该方法时,Fragment处于活动状态,用户可与之交互。
- onPause():执行该方法时,Fragment处于暂停状态,但依然可见,用户不能与之交互。
- onSaveInstanceState():保存当前Fragment的状态。该方法会自动保存Fragment的状态,比如EditText键入的文本,即使Fragment被回收又重新创建,一样能恢复EditText之前键入的文本。
- onStop():执行该方法时,Fragment完全不可见。
- onDestoryView():与onCreateView想对应,销毁与Fragment有关的视图,但未与Activity解除绑定,依然可以通过onCreateView方法重新创建视图。通常在ViewPager+Fragment的方式下会调用此方法。
- onDestroy():销毁Fragment。通常按Back键退出或者Fragment被回收时调用此方法。
- onDetach():与onAttach相对应,解除与Activity的绑定。
PS:除了onCreateView,其他的所有方法如果你重写了,必须调用父类对于该方法的实现。
3. java.lang.IllegalStateException: Fragment already added异常
描述:在使用Fragment传递参数,书写的代码如下。Fragment第一次调用时没问题,但当第二次调用这个方法时,出现java.lang.IllegalStateException: Fragment already added异常。
//切换到第一页面
if (fragone == null) {
fragone = new OneFragment();
}
Bundle bundle = new Bundle();
bundle.putString("key", "哈哈");
//将数据添加到fragment中
fragone.setArguments(bundle);
transaction.replace(R.id.frameLayout, fragone);
解决方案:
出现异常的原因是:已经实例化的Fragment不能再次传递数据。源码如下:
/**
* Supply the construction arguments for this fragment. This can only
* be called before the fragment has been attached to its activity; that
* is, you should call it immediately after constructing the fragment. The
* arguments supplied here will be retained across fragment destroy and
* creation.
*/
public void setArguments(Bundle args) {
if (mIndex >= 0) {
throw new IllegalStateException("Fragment already active");
}
mArguments = args;
}
解决方法:1. 可在fragment中添加一个全局变量设置setter和getter方法,在宿主activity通过setter与getter传递数据。2. 可判断fragment只有在它第一次实例化时候传递参数。3. 可判断fragment不等于null的时候将它置为空再次实例化它。