Fragment切替機能の迅速な実現

28340 ワード

1.はじめに
  • の1つのappトップページは通常Activity + Fragmentの形式で展示され、Fragmentの表示と非表示を制御するには基本的に2つの実現方法がある.
  • ViewPager、例えば微信、利点はジェスチャー操作がもっと便利で、公式はFragmentPagerAdapterを提供して私たちがデータのロードを実現するのに便利です(Fragmentは怠惰なロードの方式を使って、資源を浪費しないようにします)、劣勢はあなたの最初のFragmentの中ですでにViewPagerを使用して、2つの層が一緒に事件が衝突することができます.しかも操作も友好的ではありません.
  • FragmentManager、例えばトップバーは、ViewPagerの組み合わせFragmentを使用する問題に対して、FragmentManagerを使用してFragmentの表示と非表示を制御し、怠惰なロードの問題を考慮する必要はありませんが、スライドはサポートされません.

  • よく使われる機能である以上、自然に分離し、次回の重複作業を避けるために、本稿では主にこの機能の実現を紹介する.

  • 2.最初の案
  • 最初のスキームは、ActivityのベースクラスMultiFragmentActivityを定義し、ベースクラスでFragmentを切り替えるロジックを実現し、その機能を実現しようとするActivityがベースクラスを継承すれば切替機能を実現できる.MultiFragmentActivity.JAvaソースコード、この実装はもっと簡単に使用できますが、問題があります.プロジェクト全体で同じベースクラスを実現して類似または同じ機能を達成することができます.もちろん、MultiFragmentActivityをプロジェクトのベースクラスから継承し、MultiFragmentActivityを継承することができますが、この機能をLibraryに置くことができます.後で使いやすくなると、継承方式を採用できないという問題に直面します.
  • 継承を少なくし、組合せを多用することによる問題は結合性が高く、機能を分離するのに不便であるため、組合せの方法で再設計し、ヘルプクラスFragmentHelperを定義することにした.ActivityはFragmentHelperを持ってFragmentの切り替えを完了することができ、エージェントの切り替えロジックはFragmentHelperによって処理される.

  • 3.インタフェースの定義
  • まずFragmentOperatorインタフェースを定義し、このインタフェースFragmentHelper接続を介してActivity
  • を保持する
    
        interface FragmentOperator {
            /**
             *     fragment   id
             *
             * @return id
             */
            int getFragmentContainerId();
    
            /**
             *   fragment
             *
             * @param showItem      fragment pos
             * @return fragment
             */
            Fragment makeFragment(int showItem);
    
            /**
             *          ,     
             *
             * @return FragmentTransaction
             */
            void beginTransaction(FragmentTransaction transaction);
    
            /**
             *            
             *
             * @param selectImage     item
             */
            void syncSelectState(int selectImage);
    
            /**
             *         
             *
             * @param showItem    item
             * @return   false           
             */
            boolean whenShowSameFragment(int showItem);
    
            /**
             *            
             *
             * @param showItem    item
             * @return   false           
             */
            boolean whenShowNotSameFragment(int showItem);
        }
    
         //       
        public static abstract class SimpleFragmentOperator implements FragmentOperator {
            @Override
            public boolean whenShowNotSameFragment(int showItem) {
                return true;
            }
    
            @Override
            public boolean whenShowSameFragment(int showItem) {
                return false;
            }
    
            @Override
            public void syncSelectState(int selectImage) {
    
            }
    
            @Override
            public void beginTransaction(FragmentTransaction transaction) {
    
            }
        }

    4.コアメソッド
  • tagをタグとしてfragmentを追加し、
  • の重複作成を回避する.
        private static final String FRAGMENT_ATG = "FragmentHelper";
        private static final String ITEM_HIDE = "mHideItem";
        private static final String ITEM_SHOW = "mShowItem";
    
        private FragmentOperator operator;
        private Fragment mCurrentFragment;
        private FragmentManager mFragmentManager;
        private int mShowItem, mHideItem;
        private int mExactlyItem = 0;
    
    
    
        /**
         *        fragment,       fragment
         *
         * @param hideItem        fragment
         * @param showItem        fragment
         * @param isOnCreate        OnCreate   ,    false
         */
        private void performSelectItem(int hideItem, int showItem, boolean isOnCreate) {
            //         tag
            String currentTag = getFragmentTag(hideItem);
            //       fragment
            FragmentTransaction transaction = mFragmentManager.beginTransaction();
            operator.beginTransaction(transaction);
    
            //      ,     ,     ,    
            if (mFragmentManager.getFragments() == null) {
                mShowItem = showItem;
                mExactlyItem = showItem;
                mCurrentFragment = operator.makeFragment(showItem);
                transaction.add(operator.getFragmentContainerId(), mCurrentFragment, getFragmentTag(showItem))
                        .show(mCurrentFragment);
            } else {
                //   ,        ,   fragment         ,       
                if (isOnCreate && mFragmentManager.getFragments() != null) {
                    for (Fragment fragment : mFragmentManager.getFragments()) {
                        transaction.hide(fragment);
                    }
                } else {
                    //         ,       
                    Fragment lastFragment = mFragmentManager.findFragmentByTag(currentTag);
                    if (lastFragment != null) {
                        transaction.hide(lastFragment);
                    }
                }
    
    
                //         tag
                String toTag = getFragmentTag(showItem);
                // find    Fragment
                mCurrentFragment = mFragmentManager.findFragmentByTag(toTag);
                if (mCurrentFragment != null) {
                    //        
                    transaction.show(mCurrentFragment);
                } else {
                    //         fragment
                    mCurrentFragment = operator.makeFragment(showItem);
                    if (mCurrentFragment != null) {
                        transaction.add(operator.getFragmentContainerId(), mCurrentFragment, toTag);
                    }
                }
            }
            //     
            operator.syncSelectState(showItem);
            //       fragment item
            mHideItem = hideItem;
            mShowItem = showItem;
            transaction.commitAllowingStateLoss();
        }

    5.ActivityにFragmentを表示する
  • Activityで使用する場合はshowFragmentメソッドを呼び出すだけで
  •     /**
         *     fragment
         *
         * @param showItem    item
         */
        public void showFragment(int showItem) {
            showFragment(showItem, false);
        }
    
    
        /**
         *      fragment
         *
         * @param showItem      item
         * @param isOnCreate        
         */
        private void showFragment(int showItem, boolean isOnCreate) {
            if (showItem == mShowItem) {
                if (operator.whenShowSameFragment(showItem)) {
                    performSelectItem(mExactlyItem, showItem, isOnCreate);
                    mExactlyItem = showItem;
                }
            } else {
                performSelectItem(mExactlyItem, showItem, isOnCreate);
                mExactlyItem = showItem;
            }
        }

    6.最適化
  • Activityが回収すると、前回の状態
  • が記録される.
        public void restoreFragmentHelper(Bundle save) {
            if (save != null) {
                mHideItem = save.getInt(ITEM_HIDE, 0);
                mShowItem = save.getInt(ITEM_SHOW, 0);
            }
            performSelectItem(mHideItem, mShowItem, true);
        }
    
    
        public void onSaveInstanceState(Bundle outState) {
            outState.putInt(ITEM_HIDE, mHideItem);
            outState.putInt(ITEM_SHOW, mShowItem);
        }

    7.使用
    public class HomePageActivity extends BaseReaperActivity {  
    
        private FragmentHelper fragmentHelper;
    
        private FragmentHelper.SimpleFragmentOperator operator = new FragmentHelper.SimpleFragmentOperator() {
            @Override
            public int getFragmentContainerId() {
                return R.id.home_container;
            }
    
            @Override
            public Fragment makeFragment(int showItem) {
                Fragment fragment = null;
                switch (showItem) {
                    case 0:
                        fragment = HomeVideoFunFragment.newInst();
                        break;
                    case 1:
                        fragment = HomeFunnyFragment.newInst();
                        break;
                    case 2:
                        fragment = HomeBeautyFragment.newInst();
                        break;
                    case 3:
                        fragment = HomeMineFragment.newInst();
                        break;
                }
                return fragment;
            }
    
            @Override
            public void beginTransaction(FragmentTransaction transaction) {
                super.beginTransaction(transaction);
                Logger.e("beginTransaction");
            }
    
            @Override
            public void syncSelectState(int selectImage) {
                for (int i = 0; i < mBotTabsTv.size(); i++) {
                    mBotTabsTv.get(i).setSelected(selectImage == i);
                }
            }
    
            @Override
            public boolean whenShowNotSameFragment(int showItem) {
                JCVideoPlayer.releaseAllVideos();
                return super.whenShowNotSameFragment(showItem);
            }
        };
    
    
        @Override
        public void onInitViews(View view, Bundle saveData) {
            super.onInitViews(view, saveData);
            fragmentHelper = new FragmentHelper(getSupportFragmentManager(), operator);
            fragmentHelper.showFragment(2);
        }
    
        @OnClick({R.id.home_recommend, R.id.home_album, R.id.home_search, R.id.home_mine})
        public void click(View v) {
            int tag = Integer.parseInt(v.getTag().toString());
            fragmentHelper.showFragment(tag);
        }
    
        @Override
        public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
            super.onSaveInstanceState(outState, outPersistentState);
            fragmentHelper.onSaveInstanceState(outState);
        }
    
        @Override
        public void onInitViews(View view, Bundle saveData) {
            super.onInitViews(view, saveData);
            fragmentHelper = new FragmentHelper(getSupportFragmentManager(), operator);
            fragmentHelper.showFragment(2);
        }
    }

    8.ソースコード
    
    /**
     * Project  : CommonLib
     * Package  : com.march.lib.core.common
     * CreateAt : 2016/11/5
     * Describe :   Fragment  
     *
     * @author chendong
     */
    public class FragmentHelper {
    
        interface FragmentOperator {
            /**
             *     fragment   id
             *
             * @return id
             */
            int getFragmentContainerId();
    
            /**
             *   fragment
             *
             * @param showItem      fragment pos
             * @return fragment
             */
            Fragment makeFragment(int showItem);
    
            /**
             *          ,     
             *
             * @return FragmentTransaction
             */
            void beginTransaction(FragmentTransaction transaction);
    
            /**
             *            
             *
             * @param selectImage     item
             */
            void syncSelectState(int selectImage);
    
            /**
             *         
             *
             * @param showItem    item
             * @return   false           
             */
            boolean whenShowSameFragment(int showItem);
    
            /**
             *            
             *
             * @param showItem    item
             * @return   false           
             */
            boolean whenShowNotSameFragment(int showItem);
        }
    
        public static abstract class SimpleFragmentOperator implements FragmentOperator {
            @Override
            public boolean whenShowNotSameFragment(int showItem) {
                return true;
            }
    
            @Override
            public boolean whenShowSameFragment(int showItem) {
                return false;
            }
    
            @Override
            public void syncSelectState(int selectImage) {
    
            }
    
            @Override
            public void beginTransaction(FragmentTransaction transaction) {
    
            }
        }
    
        private static final String FRAGMENT_ATG = "FragmentHelper";
        private static final String ITEM_HIDE = "mHideItem";
        private static final String ITEM_SHOW = "mShowItem";
    
        private FragmentOperator operator;
        private Fragment mCurrentFragment;
        private FragmentManager mFragmentManager;
        private int mShowItem, mHideItem;
        private int mExactlyItem = 0;
    
    
        public void restoreFragmentHelper(Bundle save) {
            if (save != null) {
                mHideItem = save.getInt(ITEM_HIDE, 0);
                mShowItem = save.getInt(ITEM_SHOW, 0);
            }
            performSelectItem(mHideItem, mShowItem, true);
        }
    
    
        public void onSaveInstanceState(Bundle outState) {
            outState.putInt(ITEM_HIDE, mHideItem);
            outState.putInt(ITEM_SHOW, mShowItem);
        }
    
    
        public FragmentHelper(FragmentManager mFragmentManager, FragmentOperator operator) {
            this.mFragmentManager = mFragmentManager;
            this.mFragmentManager = mFragmentManager;
            this.operator = operator;
        }
    
    
        /**
         *     fragment
         *
         * @param showItem    item
         */
        public void showFragment(int showItem) {
            showFragment(showItem, false);
        }
    
    
        /**
         *      fragment,      
         *
         * @param showItem      item
         * @param isOnCreate        
         */
        private void showFragment(int showItem, boolean isOnCreate) {
            if (showItem == mShowItem) {
                if (operator.whenShowSameFragment(showItem)) {
                    performSelectItem(mExactlyItem, showItem, isOnCreate);
                    mExactlyItem = showItem;
                }
            } else {
                performSelectItem(mExactlyItem, showItem, isOnCreate);
                mExactlyItem = showItem;
            }
        }
    
        /**
         *            fragment'
         *
         * @return fragment
         */
        public Fragment getCurrentFragment() {
            return mCurrentFragment;
        }
    
        /**
         *        fragment,       fragment
         *
         * @param hideItem        fragment
         * @param showItem        fragment
         * @param isOnCreate        OnCreate   ,    false
         */
        private void performSelectItem(int hideItem, int showItem, boolean isOnCreate) {
            //         tag
            String currentTag = getFragmentTag(hideItem);
            //       fragment
            FragmentTransaction transaction = mFragmentManager.beginTransaction();
            operator.beginTransaction(transaction);
    
            //      ,     ,     ,    
            if (mFragmentManager.getFragments() == null) {
                mShowItem = showItem;
                mExactlyItem = showItem;
                mCurrentFragment = operator.makeFragment(showItem);
                transaction.add(operator.getFragmentContainerId(), mCurrentFragment, getFragmentTag(showItem))
                        .show(mCurrentFragment);
            } else {
                //   ,        ,   fragment         ,       
                if (isOnCreate && mFragmentManager.getFragments() != null) {
                    for (Fragment fragment : mFragmentManager.getFragments()) {
                        transaction.hide(fragment);
                    }
                } else {
                    //         ,       
                    Fragment lastFragment = mFragmentManager.findFragmentByTag(currentTag);
                    if (lastFragment != null) {
                        transaction.hide(lastFragment);
                    }
                }
    
    
                //         tag
                String toTag = getFragmentTag(showItem);
                // find    Fragment
                mCurrentFragment = mFragmentManager.findFragmentByTag(toTag);
                if (mCurrentFragment != null) {
                    //        
                    transaction.show(mCurrentFragment);
                } else {
                    //         fragment
                    mCurrentFragment = operator.makeFragment(showItem);
                    if (mCurrentFragment != null) {
                        transaction.add(operator.getFragmentContainerId(), mCurrentFragment, toTag);
                    }
                }
            }
            //     
            operator.syncSelectState(showItem);
            //       fragment item
            mHideItem = hideItem;
            mShowItem = showItem;
            transaction.commitAllowingStateLoss();
        }
    
    
        private String getFragmentTag(int item) {
            return FRAGMENT_ATG + item;
        }
    }