AndroidステップアップのFragmentとActivity間のデータインタラクション


1コンセプト


1なぜ


FragmentはActivityと同様にライフサイクルがあるため,一般的なbeanではなく構造関数を介して値を伝達し,異常をもたらす.

2参照リンク


ActivityとFragmentがデータを渡す2つの方法
【Fragment奥行きシリーズ4】FragmentとActivity間のデータインタラクション

2 Activity Fragmentに値を渡す


2.1最も一般的な方法は、Bundleを使用してパラメータを渡すことです。


(1)宿主Activity/FragmentAdapter:
Bundle bundle = new Bundle();
bundle.putString(Constant.INTENT_ID, productId);
Fragment fragment = null;
switch (position) {
     case 0:
        fragment = new ProductImageDetailFragment();
        break;

     case 1:
        fragment = new ProductParamFragment();
        break;

     case 2:
        fragment = new ProductCommentFragment();
        break;

     default:
        break;
}
fragment.setArguments(bundle);

(2)Activity/FragmentAdapter:
FragmentのonCreatView/onStart()メソッドでは、getArgments()メソッドでbundleオブジェクトを取得し、getStringのkey値で私たちが渡した値を取得します.
    @Override
    public void onStart() {
        super.onStart();
        if (isAdded()) {// Fragment Activity
            productId = getArguments().getString(Constant.INTENT_ID);
        }
    }

2.2第2の方法は、ホストActivityでメソッドを定義し、渡す値をFragmentに渡し、FragmentのonAttachメソッドでこの値を取得することである。


(1)宿主activityにおけるgetTitles()メソッド
public String getTitles(){
    return "hello";
}

(2)FragmentにおけるonAttachメソッド
@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    titles = ((MainActivity) activity).getTitles();// activity, 
}

2.3第三の方法は、Fragmentの作成と数値の伝達を拡張することです。


(1)宿主activityでFragmentを作成する
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.setCustomAnimations(android.R.anim.fade_in,android.R.anim.fade_out);
fragment1 = MyFragment.newInstance(" fragment");// , fragment
fragment2 = MyFragment.newInstance(" fragment");

(2)Fragment中
// newInstance() 
static MyFragment newInstance(String s){
        MyFragment myFragment = new MyFragment();
        Bundle bundle = new Bundle();
        bundle.putString("DATA",s);
        myFragment.setArguments(bundle);
        return myFragment;
    }

// , onCreatView 
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        //......
        Bundle bundle = getArguments();
        String data = bundle.getString("DATA");

    }

3 Fragment Activityに値を渡す


3.1手順


(1)fragmentに内部コールバックインタフェースを定義し、fragmentを含むactivityにコールバックインタフェースを実装させることで、fragmentはコールバックメソッドを呼び出してactivityにデータを渡すことができる.実はインタフェースコールバックの原理はすべて同じで、以前のブログでは、インタフェースコールバックはjavaの異なるオブジェクト間のデータ相互作用の共通の方法だと話していました.
(2)activity実装済みインタフェースはどのようにさっきのfragmentに伝わりますか?fragmentがactivityに追加されるとfragmentのメソッドonAttach()が呼び出されます.このメソッドでは、activityがOnArticleSelectedListenerインタフェースを実装しているかどうかを確認するのに適しています.チェックメソッドは、受信したactivityのインスタンスをタイプ変換し、fragmentで定義したインタフェースに値を付与することです.
(3)あるfragmentがactivityから剥離されるとonDetachメソッドが呼び出され,このとき伝達されたactivityオブジェクトを解放しなければactivityの破棄に影響し,不要なエラーが発生する.注意onAttachメソッドのコードを見て、付与する前にActivityでこのインタフェースが実装されているかどうかを判断し、instanceofを使用します.インタフェースが実装されていない場合は、例外を放出します.

3.2例


(1)宿主activityでFragmentを作成する
public class MainActivity extends Activity implements MenuFragment.FragmentInteraction{

    private TextView textView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        textView = (TextView) findViewById(R.id.content_text);
    }

    // 3.2 + , 
    @Override
    public void process(String str) {
        if (str != null) {
            textView.setText(str);
        }
    }
}

(2)Fragment中
public class MenuFragment extends Fragment implements View.OnClickListener {

    // 2.1  activity , activity
    private FragmentInteraction listterner;

    // 1  activity 
    public interface FragmentInteraction {
        void process(String str);
    }

    //  FRagmen activity 
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        if(activity instanceof FragmentInteraction) {
            listterner = (FragmentInteraction)activity; // 2.2  activity 
        } else{
            throw new IllegalArgumentException("activity must implements FragmentInteraction");
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_menu, container, false);
        View btn = view.findViewById(R.id.tv_button);
        View btn_m = view.findViewById(R.id.movie_button);
        if (btn != null||btn_m!=null) {
            btn.setOnClickListener(this);
            btn_m.setOnClickListener(this);
        }
        return view;
    }

    @Override
    public void onClick(View v) {
        int id  = v.getId();
        switch (id) {
            case R.id.tv_button:
                listterner.process(" "); // 3.1  
                break;
            case R.id.movie_button:
                listterner.process(" ");
                break;
        }
    }

    // activity 
    @Override
    public void onDetach() {
        super.onDetach();
        listterner = null;
    }
}

4 FragmentとFragmentの間の伝達値


ActivityにFragmentをロードする場合、複数のFragmentを使用して切り替え、別のFragment、つまり2つのFragment間でパラメータの伝達を行う場合があります.2つの方法があります.

4.1共通のActivityによる伝達(主な方法)


Activityにフィールドを追加し、その値を保存します.Activityでフィールドを定義し、setメソッドとgetメソッドを追加します.
(1)宿主activityにおいて
public class DemoActivity {

    private String mTitle;

    public String getmTitle() {
        return mTitle;
    }

    public void setmTitle(String title) {
        this.mTitle = title;
    }

}

(2)Fragment中
//  、 
((DemoActivity)getActivity()).getmTitle();

4.1 Bundleによる伝達(本質はActivity->Fragment)


(1)宿主activityにおいて
ft.hide(getActivity().getSupportFragmentManager().findFragmentByTag(""));
    DemoFragment demoFragment = new DemoFragment();  
    Bundle bundle = new Bundle();  
    bundle.putString("key", " ");  
    demoFragment.setArguments(bundle);  
    ft.add(R.id.fragmentRoot, demoFragment, SEARCHPROJECT);  
    ft.commit();  

(2)Fragment中
String string = getArguments().getString("key");