view

View-Fragment

2020-04-14  本文已影响0人  isLJli
1.fragmentPagerAdapter和fragmentStatePagerAdapter的区别

都是继承PagerAdapter,viewpager的setAdapter()就可以传它们做参数。多一个state是将fragment彻底移除。
作用:通过传给它们一个FragmentManager,它就可以帮我们绑定和删除fragment。它们的的构造函数就是传一个fragmentManager,如果当前fragment的宿主是activity,那么它的fragmentManager就是getSupportFragmentManager(),如果宿主是fragment,那么它的fragmentManager就是getChildFragmentManager()。通常给viewpager做适配器。

它们的区别:fragmentPagerAdapter适合数据量小,在删除数据时只调用了detach()将fragment与宿主解绑,没有将fragment删除。

fragmentStatePagerAdapter适合数据量大,在绑定数据时有一个List来缓存fragment,但是在删除时则直接调用remove()将fragment删除,所以在滑动下一个fragment之后,它就会被彻底删除。

2.FragmentTransaction的replace、add、remove方法?
protected void initData() {
      FragmentManager fragmentManager = getSupportFragmentManager();
      FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
      mHomeFragment = new HomeFragment();
      fragmentTransaction.add(R.id.main_tab_fl, mHomeFragment);
      fragmentTransaction.commit();
  }

add:就是将fragment一层一层叠加到frameLayout。

public FragmentTransaction add(int containerViewId, Fragment fragment) {
      doAddOp(containerViewId, fragment, null, OP_ADD);
      return this;
  }

  private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
      fragment.mFragmentManager = mManager;

      // tag可以说是唯一标识我们可以通过它从FragmentManager中找到对应的Fragment
      if (tag != null) {
          if (fragment.mTag != null && !tag.equals(fragment.mTag)) {
              throw new IllegalStateException("Can't change tag of fragment "
                      + fragment + ": was " + fragment.mTag
                      + " now " + tag);
          }
          fragment.mTag = tag;
      }

      if (containerViewId != 0) {
          if (fragment.mFragmentId != 0 && fragment.mFragmentId != containerViewId) {
              throw new IllegalStateException("Can't change container ID of fragment "
                      + fragment + ": was " + fragment.mFragmentId
                      + " now " + containerViewId);
          }
          // 把Fragment的ContainerId和FragmentId指定为我们传递过来的布局中的ViewGroup的id。
          fragment.mContainerId = fragment.mFragmentId = containerViewId;
      }

      // 见名思意 Op是什么?就当是一些基本参数吧
      Op op = new Op();
      op.cmd = opcmd;
      op.fragment = fragment;
      addOp(op);
  }

  void addOp(Op op) {
      if (mHead == null) {
          mHead = mTail = op;
      } else {
          op.prev = mTail;
          mTail.next = op;
          mTail = op;
      }
      op.enterAnim = mEnterAnim;
      op.exitAnim = mExitAnim;
      op.popEnterAnim = mPopEnterAnim;
      op.popExitAnim = mPopExitAnim;
      mNumOp++;
  }

commite()方法才真正执行,添加操作

void moveToState(Fragment f, int newState, int transit, 
  int transitionStyle, boolean keepActive){
              // ... 省略部分代码
              f.onAttach(mHost.getContext());
              // 这个方法一调用就会执行Fragment的onAttach(Activity activity)这个生命周期方法
              if (f.mParentFragment == null) {
                  mHost.onAttachFragment(f);
              }

              if (!f.mRetaining) {
                  f.performCreate(f.mSavedFragmentState);
                  // 执行生命周期onCreate(savedInstanceState);
              }
              f.mRetaining = false;
              if (f.mFromLayout) {
                  ViewGroup container = null;
                  if (f.mContainerId != 0) {
                       //从activity中找到我们需要存放Fragment的ViewGroup布局
                       container = (ViewGroup)mContainer.onFindViewById(f.mContainerId);
                       if (container == null && !f.mRestored) {
                            throwException(new IllegalArgumentException(
                                 "No view found for id 0x"
                                 + Integer.toHexString(f.mContainerId) + " ("
                                 + f.getResources().getResourceName(f.mContainerId)
                                 + ") for fragment " + f));
                      }
                  }
                  // For fragments that are part of the content view
                  // layout, we need to instantiate the view immediately
                  // and the inflater will take care of adding it.
                  f.mView = f.performCreateView(f.getLayoutInflater(
                      f.mSavedFragmentState), null, f.mSavedFragmentState);
                  // 这个方法过后会执行onCreateView()生命周期且f.mView就是我们自己覆盖Fragment返回的View
                  if (f.mView != null) {
                      f.mInnerView = f.mView;
                      // v4包兼容11以下的版本我还是没说错啊
                      if (Build.VERSION.SDK_INT >= 11) {
                          ViewCompat.setSaveFromParentEnabled(f.mView, false);
                      } else {
                          f.mView = NoSaveStateFrameLayout.wrap(f.mView);
                      }

                      if (container != null) {
                          Animation anim = loadAnimation(f, transit, true,
                          transitionStyle);
                          if (anim != null) {
                                setHWLayerAnimListenerIfAlpha(f.mView, anim);
                                f.mView.startAnimation(anim);
                          }
                          // 如果ViewGroup不等于null就把从onCreateView()生命周期中获得的View添加到该布局中
                          // 最主要的就是这个方法,其实我们可以把Fragment理解成一个自定义的类
                          // 通过onCreateView()获取的到View添加到一个FragmentActivity的一个ViewGroup中
                          // 只不过它有自己的生命周期而已......
                          container.addView(f.mView);
                      }
                      // 如果是隐藏那就设置为不可见
                      if (f.mHidden) f.mView.setVisibility(View.GONE);
                      // 执行onViewCreated()生命周期方法
                      f.onViewCreated(f.mView, f.mSavedFragmentState);
                  } else {
                      f.mInnerView = null;
                  }

                  f.performActivityCreated(f.mSavedFragmentState);
                  if (f.mView != null) {
                      f.restoreViewState(f.mSavedFragmentState);
                  }
                  f.mSavedFragmentState = null;
              }
              // 代码省略......
       }
}
// 后面的我们就不看了,这上面的代码我自己做了一些整合,把它连贯起来了
// 因为我们把add方法写在了Activity中的onCreate()方法中所以做了一些处理......

remove:将frameLayout的fragment一层层去掉

replace:将replace相当于执行了remove和add,会remove相同id的所有Fragment,然后再把这个Fragment放进去

public FragmentTransaction replace(int containerViewId, Fragment fragment, String tag) {
      if (containerViewId == 0) {
          throw new IllegalArgumentException("Must use non-zero containerViewId");
      }

      doAddOp(containerViewId, fragment, tag, OP_REPLACE);
      return this;
  }
if (mManager.mAdded != null) {
  for (int i = mManager.mAdded.size() - 1; i >= 0; i--) {
      Fragment old = mManager.mAdded.get(i);
      if (old.mContainerId == containerId) {
           if (old == f) {
               op.fragment = f = null;
           } else {
              if (op.removed == null) {
                  op.removed = new ArrayList<Fragment>();
              }
              op.removed.add(old);
              old.mNextAnim = exitAnim;
              if (mAddToBackStack) {
                  old.mBackStackNesting += 1;
              }
              mManager.removeFragment(old, transition, transitionStyle);
          }
      }
  }
}
if (f != null) {
  f.mNextAnim = enterAnim;
  mManager.addFragment(f, false);
}
image.png

3.碎片的生命周期
有11个方法,其中活动的6个方法都有(除了restart),

onAttach()碎片与活动关联,
onCreate()
onCreateView()创建碎片布局,
onActivtyCreated()碎片与活动都创建好
onstart(),
onResume(),
onPause(),
onStop,
onDestoryView()碎片视图被移除
onDestroy(),
onDetach()碎片与活动解除关联。

4.fragment的通信

Bundle和setArguments(bundle)1.handler、2.广播、3.EventBus、4.接口回调、

1.handler:在activity/fragment实例handler,然后在fragment拿到actvity的handler,然后通过handler发送消息。fragment可以通过getActivity()拿到宿主activity。(只能单向传输数据)

image

示意图

2.广播:fragment发送广播,activity/fragment接收广播(不能传输数据)

在要接收的activity/fragmen注册广播,不过不能向它传播数据。

image

示意图

3.EventBus:在要接收的activity/frament中注册/反注册事件,并通过注解方法接收对象并处理。(单向传输一个对象)

image

示意图

在发送frgment:

EventBus.getDefault().post(对象);

4.接口回调:activity通过继续接口,同时实现实现接口的抽象方法,抽象的方法的参数就是传递过来的数据,发送的fragment通过拿到接口的实例,通过接口的实例调用方法,写入参数。

在fragment中定义接口和在onattach()方法在获取activity的实例

image

示意图

在activity中实现接口:

image

示意图

5.Bundle和setArguments(bundle):如果有实例化的fragment时,可以通过setArguments(bundle)来给fragment来传输数据。(单向传输数据)

image

示意图

image

示意图

5.fragment的懒加载:

文章

上一篇下一篇

猜你喜欢

热点阅读