web-dev-qa-db-ja.com

フラグメントとアクティビティ間の通信-ベストプラクティス

この質問は、主に私のアプリを処理する最良の方法について意見を求めることです。 1つのアクティビティで処理される3つのフラグメントがあります。フラグメントAには写真のクリック可能な要素が1つあり、フラグメントBにはボタンのクリック可能な要素が4つあります。他のフラグメントは、写真がクリックされたときに詳細を表示するだけです。 ActionBarSherlockを使用しています。

Screen shot

進むボタンと戻るボタンは、それぞれ写真を次または前のポーズに変更する必要があります。写真とボタンを同じフラグメントに保持することもできますが、タブレットでそれらを再配置したい場合に備えて、それらを別々にしたかったです。

アドバイスが必要です-フラグメントAとBを組み合わせる必要がありますか?そうでない場合は、3つのクリック可能なアイテムのインターフェースを実装する方法を理解する必要があります。

Roboguiceを使用することを検討しましたが、SherlockFragmentActivityを使用して既に拡張しているので、手間がかかりません。 Ottoの言及を見ましたが、プロジェクトに含める方法に関する良いチュートリアルは見ませんでした。デザインのベストプラクティスはどうあるべきだと思いますか?

また、フラグメントとアクティビティの間の通信方法を理解するのに助けが必要です。ポーズIDなど、アプリケーション内の一部のデータを「グローバル」に保持したいと思います。ストックAndroid開発者情報以外に表示できるサンプルコードはありますか?それだけではありません。

ところで、私はすでに各ポーズに関するすべての情報をSQLiteデータベースに保存しています。それは簡単な部分です。

54
Kristy Welsh

アクティビティとフラグメント間で通信する最も簡単な方法は、インターフェースを使用することです。基本的には、特定のフラグメントA内でインターフェイスを定義し、アクティビティにそのインターフェイスを実装させることです。

そのインターフェイスを実装すると、オーバーライドするメソッドで必要な処理を実行できます。

インターフェースのもう1つの重要な部分は、フラグメントから抽象メソッドを呼び出し、それをアクティビティにキャストすることを忘れないことです。正しく行われない場合、ClassCastExceptionをキャッチする必要があります。

Simple Developer Blog に、この種のことを正確に行う方法に関する優れたチュートリアルがあります。

これがお役に立てば幸いです!

73
Eenvincible

フラグメント間で通信するための推奨される方法は、メインアクティビティによって管理されるコールバック\リスナーを使用することです。

このページのコードはかなり明確だと思います: http://developer.Android.com/training/basics/fragments/communicating.html

事実上の参照アプリとして設計されたIO 2012 Scheduleアプリも参照できます。ここにあります: http://code.google.com/p/iosched/

また、ここにSOの質問と良い情報があります: フラグメント間でデータを渡す方法

23
Booger

コールバックインターフェイスによって実装されます。まず、インターフェイスを作成する必要があります。

public interface UpdateFrag {
     public void updatefrag();
    }

アクティビティでは、次のコードを実行します。

UpdateFrag updatfrag ;
public void updateApi(UpdateFrag listener) {
        updatfrag = listener;
   }

コールバックがアクティビティで発生するイベントから:

updatfrag.updatefrag();

FragmentでCreateViewのインターフェイスを実装し、次のコードを実行します。

 ((Home)getActivity()).updateApi(new UpdateFrag() {
                @Override
                public void updatefrag() {
                   .....your stuff......
                }
            });
11
Jyoti

キャストを行えるアノテーションライブラリを作成しました。これをチェックしてください。 https://github.com/zeroarst/callbackfragment/

@CallbackFragment
public class MyFragment extends Fragment {

    @Callback
    interface FragmentCallback {
       void onClickButton(MyFragment fragment);
    }    
    private FragmentCallback mCallback;

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.bt1
                mCallback.onClickButton(this);
                break;
            case R.id.bt2
                // Because we give mandatory = false so this might be null if not implemented by the Host.
                if (mCallbackNotForce != null)
                mCallbackNotForce.onClickButton(this);
                break;
        }
    }
}

次に、フラグメントのサブクラスを生成します。そして、それをFragmentManagerに追加するだけです。

public class MainActivity extends AppCompatActivity implements MyFragment.FragmentCallback {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        getSupportFragmentManager().beginTransaction()
            .add(R.id.lo_fragm_container, MyFragmentCallbackable.create(), "MY_FRAGM")
            .commit();
    }

    Toast mToast;

    @Override
    public void onClickButton(MyFragment fragment) {
        if (mToast != null)
            mToast.cancel();
        mToast = Toast.makeText(this, "Callback from " + fragment.getTag(), Toast.LENGTH_SHORT);
        mToast.show();
    }
}
4
Arst

ActivityFragmentsの間で通信するには、いくつかのオプションがありますが、多くの読書と多くの経験の後、この方法で再開できることがわかりました。

  • Activityは、子Fragmentと通信したい=>単純にFragmentクラスにパブリックメソッドを記述し、Activityがそれらを呼び出すようにする
  • Fragmentが親と通信したいActivity =>これには、公式のAndroidリンク https://developer.Android.com/training/basics/fragments/communicatingのように、もう少し作業が必要です は、interfaceによって実装されるActivityを定義し、そのActivityと通信したい任意のFragmentのコントラクトを確立することをお勧めします。たとえば、それを含むFragmentAと通信したいactivityがある場合は、FragmentAInterfaceを定義して、それを使用することを決定したFragmentAに対してactivitiesが呼び出すことができるメソッドを定義します。
  • Fragmentは他のFragmentと通信したい=>これは、最も「複雑な」状況に陥る場合です。 FragmentAからFragmentBへ、またはその逆にデータを渡す必要がある可能性があるため、FragmentAInterfaceで実装されるFragmentBFragmentAInterfaceで実装されるFragmentAの2つのインターフェースを定義することになります。それは物事を面倒にし始めます。そして、さらに数個のFragmentsが配置されていて、親のactivityでさえも通信したい場合を想像してください。さて、このケースはViewModelactivitysの共有fragmentを確立する絶好の機会です。詳細はこちら https://developer.Android.com/topic/libraries/architecture/viewmodel 基本的に、SharedViewModelactivityの間で共有するすべてのデータが含まれるfragmentsクラスを定義する必要があります。

ViewModelの場合、コード内で物事を汚したり面倒なものにする余分なロジックを追加する必要がないため、最後に物事がかなり単純になります。さらに、データの収集(SQLiteデータベースまたはAPIの呼び出しによる)をControlleractivitiesおよびfragments)から分離できます。

4
xarlymg89

アクティビティ、フラグメント、サービスなどの間で通信する方法はいくつかあります。明白な方法は、インターフェースを使用して通信することです。ただし、それは生産的なコミュニケーション方法ではありません。リスナーなどを実装する必要があります。

私の提案は、イベントバスを使用することです。イベントバスは、パブリッシュ/サブスクライブパターンの実装です。

アクティビティでイベントをサブスクライブしてから、そのイベントをフラグメントなどに投稿できます。

ここで 私のブログ投稿で このパターンについての詳細を見つけることができ、 例のプロジェクト 使用法を示します。

2
Gunhan

あなたが何をしたいのか本当に理解したかどうかはわかりませんが、フラグメント間で通信するための推奨される方法は、アクティビティ間でコールバックを使用することです。こちらをご覧ください http://developer.Android.com/training/basics/fragments/communicating.html

1
alex

フラグメント内の関数宣言を使用してパブリックインターフェイスを宣言し、アクティビティにインターフェイスを実装できます。次に、フラグメントから関数を呼び出すことができます。

0
Jacob Abraham

私はインテントを使用して、アクションをメインアクティビティに伝えています。主なアクティビティは、onNewIntent(Intent intent)をオーバーライドしてこれらをリッスンします。メインアクティビティは、たとえばこれらのアクションを対応するフラグメントに変換します。

そのため、次のようなことができます。

public class MainActivity extends Activity  {

    public static final String INTENT_ACTION_SHOW_FOO = "show_foo";
    public static final String INTENT_ACTION_SHOW_BAR = "show_bar";


   @Override
   protected void onNewIntent(Intent intent) {
        routeIntent(intent);
   }

  private void routeIntent(Intent intent) {
       String action = intent.getAction();
       if (action != null) {               
            switch (action) {
            case INTENT_ACTION_SHOW_FOO:
                // for example show the corresponding fragment
                loadFragment(FooFragment);
                break;
            case INTENT_ACTION_SHOW_BAR:
                loadFragment(BarFragment);
                break;               
        }
    }
}

次に、fooフラグメントを表示するフラグメント内:

Intent intent = new Intent(context, MainActivity.class);
intent.setAction(INTENT_ACTION_SHOW_FOO);
// Prevent activity to be re-instantiated if it is already running.
// Instead, the onNewEvent() is triggered
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
getContext().startActivity(intent);
0
Pepster