这个我在别的论坛发过现在在这里也写一下
自从fragment出现以来现在越来越多的项目用了这个东西,
下面总结一下遇到的一些问题和解决方案如果有更好的解决办法 欢迎回复
这些问题归结一点都是fragment生命周期和缓存引起的,下面是一些常见问题
1 viewpage+fragmentPageAdapter 刷新问题
描述 :
动态创建fragment 调用mFragmentPagerAdapter.notifyDataSetChanged发现部分,或者全部的fragment没有变化
这种情况一般出现在fragment1,fragment2,fragment3.....当某些情况下fragment2 里面数据元素发生了改变,导致UI需要更改,这个时候我们需要和listview一样调用mFragmentPagerAdapter.notifyDataSetChanged方法来刷新页面
原因:
如果fragment2已经创建(如果显示过),系统会在FragmentManager里面去找已经创建过的对象,如果存在那么再次需要显示时候直接找以前的对象
下面是系统fragment的源码处理的方式:
解决方案:
方法一是改变fragment的tag,还一种直接清空以前对象(fm 是构造方法传递的FragmentManager)
public void setFragments(ArrayList<Fragment> fragments) {
if(this.fragments != null){
FragmentTransaction ft = fm.beginTransaction();
for(Fragment f:this.fragments){
ft.remove(f);
}
ft.commit();
ft=null;
fm.executePendingTransactions();
}
this.fragments = fragments;
notifyDataSetChanged();
}
当然 如果你能明确知道是哪一个fragment
可以这样
for(Fragment f:this.fragments){
if(f.getTag().equals(currentFragment.getTag()))
{
ft.remove(f);
}
}
2 横竖屏切换时候空指针问题
描述:
我们在用Activity时候,横竖屏切换会调用activity的 oncreate(未对activity做任何设置时候 ),
fragmentActivity也有类似问题,他还会导致fragment我们用构造方法传递的数据清空原因:
当横竖屏切换是 当前FragmentActivity中的fragment都会通过Fragment.instantiate重新生成,方法将使用默认的构造函数onCreate来生成相应的Fragment如果创建fragment 没有继承这个,那么重新生成的就不会得到你赋的值,那么在你调用的时候就会空指针了
解决方法:
public String imgPath;
public String imgId;
public static DetailFragment newInstance(String id,String path) {
DetailFragment f = newDetailFragment();
// Supply num input as an argument.
Bundle args = newBundle();
args.putString("id", id);
args.putString("path", path);
f.setArguments(args);
return f;
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle bundle = getArguments();
if(bundle != null) {
imgId = bundle.getString("id");
imgPath = bundle.getString("path");
}
}
这个问题简单 mainfest.xml文件修改下activity配置 多了一个属性
android:configChanges="orientation|keyboard|keyboardHidden|screenSize"
4 FragmentActivity 与fragment之间信息传递
用接口处理2者之间的信息传递
public interface SetShowDataTypeListener {
public void setDataType(int position);
}
SetShowDataTypeListener mCallback;
btn.setOnClickListener(newOnClickListener() {
@Override
publicvoidonClick(View v) {
mCallback.setDataType(0);
}
});
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// 确认容器activity已经实现接口
// the callback interface. If not, it throws an exception
// 回调接口。如果没有,抛出异常
try{
mCallback = (SetShowDataTypeListener) activity;
}catch(ClassCastException e) {
thrownewClassCastException(activity.toString() + " must implement SetShowDataTypeListener");
}
}
5 在情况3中 如果这个fragment未创建,在activity里面去试图访问属性会出错
fragment1,fragment2,fragment3,fragment4..fragmentN
如果我有这么多个fragment 我在某些情况下需要方法fragmentN的impath数据imgPath ,因为这个fragment还未创建,这个时候imgPath就是null
可以这样在创建的时候赋值
public static DetailFragment newInstance(String id,String path) {
DetailFragment f = newDetailFragment();
f.id = id;
f.imgPath = path;
// Supply num input as an argument.
Bundle args = newBundle();
args.putString("id", id);
args.putString("path", path);
f.setArguments(args);
returnf;
}
6 Fragment生命周期
有些人可能觉得这个生命周期和官网给的不一致,其实原因是fragment有缓存,这个和activity不一样。如果某一个fragment未被释放就会直接显示,和生命周期的图完全不一样,大家可以打印log看看
7
这段时间看到论坛很多人问到fragment 加载listview ,滑动或者replace再加载以后 ,listview不显示或者adapter不调用getview等等问题
其实这个还是fragment缓存问题,fragment把内部加载的view释放了,这个时候需要重新加载一次
这样就可以了
在fragment的这个方法onActivityCreated
添加类似下面的代码即可
if(mAdapter == null)
{
// initAdapter
}
mlistview.setAdapter(mAdapter)