android fragment使用注意

本文详细探讨了Fragment在Android应用开发中的生命周期问题及缓存机制,包括刷新问题、横竖屏切换时的空指针问题、横竖屏切换事件不触发、信息传递、Fragment生命周期异常等常见问题及解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这个我在别的论坛发过现在在这里也写一下

自从fragment出现以来现在越来越多的项目用了这个东西,

下面总结一下遇到的一些问题和解决方案如果有更好的解决办法 欢迎回复

这些问题归结一点都是fragment生命周期和缓存引起的,下面是一些常见问题


1   viewpage+fragmentPageAdapter 刷新问题

描述 :

        动态创建fragment 调用mFragmentPagerAdapter.notifyDataSetChanged发现部分,或者全部的fragment没有变化

这种情况一般出现在fragment1,fragment2,fragment3.....当某些情况下fragment2 里面数据元素发生了改变,导致UI需要更改,

这个时候我们需要和listview一样调用mFragmentPagerAdapter.notifyDataSetChanged方法来刷新页面

原因:

        如果fragment2已经创建(如果显示过),系统会在FragmentManager里面去找已经创建过的对象,如果存在那么再次需要显示时候直接找以前的对象


下面是系统fragment的源码处理的方式:
  String name = makeFragmentName(container.getId(), position);
   Fragment fragment = mFragmentManager.findFragmentByTag(name);
   if(fragment != null) {
        if(DEBUG) Log.v(TAG, "Attaching item #" + position + ": f=" + fragment);
        mCurTransaction.attach(fragment);
   }else{
        fragment = getItem(position);
        if(DEBUG) Log.v(TAG, "Adding item #" + position + ": f=" + fragment);
        mCurTransaction.add(container.getId(), fragment,
        makeFragmentName(container.getId(), position));
   }



解决方案: 

       方法一是改变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");
   }
}
3 FragmentActivity 横竖屏切换事件不触发问题
这个问题简单 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)


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值