Fragmentのロールバックスタックとactivityの通信多重化と2つのアダプタの違い

20419 ワード

Fragmentのロールバックスタック


一、バックスタックとは何か


Activityを切り替えると、スタックの形式でスタックを押し出すことが知られていると信じられています.Fragmentの場合、手動でフォールバックスタックを開かなければ、直接破棄して再構築されますが、Fragmentタスクをフォールバックスタックに追加すると状況が異なり、Activityのようなスタック管理方式があります.

二、ロールバックスタックの使用(fragmentジャンプのパッケージ)

    public void startToFragment(Context context, int container, Fragment newFragment) {
        FragmentManager manager = getFragmentManager();
        FragmentTransaction transaction = manager.beginTransaction();
        transaction.replace(container, newFragment);
        transaction.addToBackStack(context.getClass().getName());
        transaction.commit();
    }

1.fragment1 --> fragment2
       Fragment2 fragment2 = new Fragment2 ();
	   startToFragment(getActivity(), R.id.layout_container, fragment2 );

2.fragment2 --> fragment1
getActivity().getFragmentManager().popBackStack();

3.fragment2 --> fragment3
      Fragment3 fragment3 = new Fragment3 ();
      startToFragment(getActivity(), R.id.layout_container, fragment3 );

4.fragment3 --> fragment1
   // Fragment Fragment
   FragmentManager fragmentManager = getFragmentManager();
   fragmentManager.popBackStackImmediate(
   MainActivity.class.getName(), FragmentManager.POP_BACK_STACK_INCLUSIVE);

activityとの通信


通常、FragmentとActivityの通信には、次の3つのケースがあります.
  • Activity操作内蔵Fragment
  • Fragment操作宿主Activity
  • Fragment操作はActivityの他のFragmentに属する
  • Androidでは、Activityとfragment間の通信を以下の方法で優雅に実現できます.
  • Handler
  • 放送
  • EventBus
  • インタフェースコールバック
  • BundleとsetArguments(bundle)
  • Handler

    public class MainActivity extends FragmentActivity{ 
          // Handler 
          public Handler mHandler = new Handler(){       
              @Override
               public void handleMessage(Message msg) { 
                    super.handleMessage(msg);
                     // 
               }
         }
         
       } 
        public class MainFragment extends Fragment{ 
              // Activity handler
               private Handler mHandler;
               @Override
               public void onAttach(Activity activity) { 
                    super.onAttach(activity);
                   
                    if(activity instance MainActivity){ 
                          mHandler =  ((MainActivity)activity).mHandler; 
                    }
               }
              
             }
    

    この方法の欠点:
  • Fragmentは具体的なActivityに結合がありFragment多重化には不利
  • メンテナンスに不利なので、該当するActivityを削除するにはFragmentも変更しなければならない
  • Activityの戻りデータが取得できない
  • だから一般的にはこの方法はお勧めしません.

    ブロードキャスト


    Activityにブロードキャスト受信機を登録し、Fragmentでブロードキャストを送信します.
    private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                if (action.equals(ACTION_NAME)) {
                    String msg = intent.getStringExtra("msg");
                    Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
                }
            }
        };
        public void registerBoradcastReceiver() {
            IntentFilter myIntentFilter = new IntentFilter();
            myIntentFilter.addAction(ACTION_NAME);
            registerReceiver(mBroadcastReceiver, myIntentFilter);
        }
        @Override
        protected void onDestroy() {
            super.onDestroy();
            unregisterReceiver(mBroadcastReceiver);
      }
    

    EventBus

  • MainActivity
  • // 
    EventBus.getDefault().register(this);
    // 
    @Subscribe
       public void onEventMainThread(UserEvent event) {
           btn.setText(event.getUserName());
           service_tv.setText(event.getUserName());
     }
    
  • Fragment送信メッセージ
  • UserEvent event=new UserEvent();
    EventBus.getDefault().post(event);
    

    インタフェースコールバック

  • Fragmentでインタフェースを定義する
  • 呼び出しインタフェースにおける抽象メソッド
  • Activityでインタフェースを実現し、インタフェースでの方法を具体的に実現し、通信を完了する
  • BundleとsetArguments(bundle)

  • Fragmentインスタンスを初期化しsetArguments:
  • DiscoverFragment discoverFragment = new DiscoverFragment();
    Bundle bundle = new Bundle();
    bundle.putString("email", email);
    discoverFragment.setArguments(bundle);
    
  • FragmentでArgumentsをもらう:
  • @Nullable
      @Override
      public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
          View view = inflater.inflate(R.layout.fragment_discover, null);
          Bundle bundle = getArguments();
          // 
          email = bundle.getString("email");
    
    
          return view;
    }
    

    Fragmentの多重化


    一、なぜ多重化するのか.
    Activityはリビルド時に含まれるFragmentManagerをリカバリし、FragmentManagerは管理するFragmentをリカバリし、同じFragmentも含まれるFragmentManagerをリカバリし、すべてのリカバリまで階層的に進みます.
    二、多重化はどのようなメリットをもたらしますか?
    エラー表示を避ける重複追加を避ける余分なメモリ消費を避けるインタフェースの起動速度を最適化するなど

    Fragmentアダプタの違い


    一、FragmentPagerAdapter
    FragmentPagerAdapterを使用すると、Fragmentオブジェクトは常にメモリに保存されるので、ページが大量に表示されている場合、FragmentPagerAdapterは使用できません.FragmentPagerAdapterはタブのような少数のpageの場合に適用されます.
    二、FragmentStatePagerAdapter
    このときFragmentStatePagerAdapterを使用することを考えてみてください.FragmentStatePagerAdapterを使用する場合、Fragmentが表示されない場合、Fragmentオブジェクトは破棄されます(スライドすると現在のインタフェースが保存され、次のインタフェースと前のインタフェースがある場合)、最大3つ保存されます.その他は破棄されますが、コールバックonDestroy()メソッドの前にonSaveInstanceState(Bundle outState)メソッドをコールバックしてFragmentの状態を保存し、次回のFragment表示時にonCreate(Bundle savedInstanceState)で格納されている状態値を取り出し、FragmentStatePagerAdapterの方がページが多い場合に適しています.