美文网首页view
View-Fragment

View-Fragment

作者: isLJli | 来源:发表于2020-04-14 17:10 被阅读0次
    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的懒加载:

    文章

    相关文章

      网友评论

        本文标题:View-Fragment

        本文链接:https://www.haomeiwen.com/subject/oespuhtx.html