私のプログラムで 2 つのフラグメント間でデータを渡そうとしています。リストに格納されている単純な文字列です。リストはフラグメント A で公開され、ユーザーがリスト項目をクリックすると、フラグメント B に表示される必要があります。コンテンツ プロバイダーは ID のみをサポートしているように見えるため、機能しません。助言がありますか?
13 に答える
Roboguice を使用する場合、Roboguice の EventManager を使用して、Activity をインターフェイスとして使用せずにデータを渡すことができます。これは非常にきれいな IMO です。
Roboguice を使用していない場合は、Otto をイベント バスとして使用することもできます: http://square.github.com/otto/
更新 20150909: Green Robot Event Bus や RxJava も使用できるようになりました。ユースケースによって異なります。
Fragment
ドキュメントから:
たとえば、ユーザー イベントに基づいてコンテンツを変更する場合など、ある Fragment が別の Fragment と通信することが必要になることがよくあります。すべてのフラグメント間の通信は、関連付けられたアクティビティを通じて行われます。2 つのフラグメントが直接通信することはありません。
そのため、ドキュメントの基本的なフラグメント トレーニング ドキュメントを参照することをお勧めします。それらは、例とウォークスルー ガイドでかなり包括的です。
したがって、フラグメントAとフラグメントBを制御するアクティビティABがあるとします。フラグメントAの内部には、アクティビティABが実装できるインターフェイスが必要です。サンプルのAndroidコードでは、次のようになっています。
private Callbacks mCallbacks = sDummyCallbacks;
/*このフラグメントを含むすべてのアクティビティが実装する必要があるコールバックインターフェイス。このメカニズムにより、アクティビティにアイテムの選択を通知できます。* /
public interface Callbacks {
/*Callback for when an item has been selected. */
public void onItemSelected(String id);
}
/*A dummy implementation of the {@link Callbacks} interface that does nothing. Used only when this fragment is not attached to an activity. */
private static Callbacks sDummyCallbacks = new Callbacks() {
@Override
public void onItemSelected(String id) {
}
};
コールバックインターフェイスは、フラグメントの1つ(フラグメントAとしましょう)の中に配置されます。このコールバックインターフェイスの目的は、任意のアクティビティで実装できるFragA内のネストされたクラスのようなものだと思います。したがって、フラグメントAがTVの場合、CallBacksはフラグメントAをアクティビティABで使用できるようにするTVリモート(インターフェイス)です。私は初心者なので、細部について間違っているかもしれませんが、プログラムをすべての画面サイズで完全に動作させることができました。これが私が使用したものです。
したがって、フラグメントAの内部には、次のものがあります:(これはAndroidのサンプルプログラムから取得しました)
@Override
public void onListItemClick(ListView listView, View view, int position, long id) {
super.onListItemClick(listView, view, position, id);
// Notify the active callbacks interface (the activity, if the
// fragment is attached to one) that an item has been selected.
mCallbacks.onItemSelected(DummyContent.ITEMS.get(position).id);
//mCallbacks.onItemSelected( PUT YOUR SHIT HERE. int, String, etc.);
//mCallbacks.onItemSelected (Object);
}
そして、アクティビティAB内で、onItemSelectedメソッドをオーバーライドします。
public class AB extends FragmentActivity implements ItemListFragment.Callbacks {
//...
@Override
//public void onItemSelected (CATCH YOUR SHIT HERE) {
//public void onItemSelected (Object obj) {
public void onItemSelected(String id) {
//Pass Data to Fragment B. For example:
Bundle arguments = new Bundle();
arguments.putString(“FragmentB_package”, id);
FragmentB fragment = new FragmentB();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction().replace(R.id.item_detail_container, fragment).commit();
}
したがって、アクティビティAB内では、基本的にすべてをバンドルに入れてBに渡します。バンドルの使用方法がわからない場合は、クラスを調べてください。
基本的にAndroidが提供するサンプルコードを使用します。DummyContentのものを持っているもの。新しいAndroidアプリケーションパッケージを作成すると、MasterDetailFlowというタイトルのパッケージになります。
1-最初の方法は、インターフェースを定義することです
public interface OnMessage{
void sendMessage(int fragmentId, String message);
}
public interface OnReceive{
void onReceive(String message);
}
2-あなたの活動でOnMessageインターフェースを実装します
public class MyActivity implements OnMessage {
...
@Override
public void sendMessage(int fragmentId, String message){
Fragment fragment = getSupportFragmentManager().findFragmentById(fragmentId);
((OnReceive) fragment).sendMessage();
}
}
3-フラグメントで OnReceive インターフェイスを実装します
public class MyFragment implements OnReceive{
...
@Override
public void onReceive(String message){
myTextView.setText("Received message:" + message);
}
}
これは、フラグメント間でのメッセージの受け渡しを処理するボイラープレート バージョンです。
フラグメント間のデータの受け渡しを処理するもう 1 つの方法は、イベント バスを使用することです。
1- イベント バスへの登録/登録解除
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
2- イベント クラスを定義する
public class Message{
public final String message;
public Message(String message){
this.message = message;
}
}
3- このイベントをアプリケーションの任意の場所に投稿します
EventBus.getDefault().post(new Message("hello world"));
4-そのイベントをサブスクライブして、フラグメントで受信します
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessage(Message event){
mytextview.setText(event.message);
}
詳細、ユースケース、およびイベント バス パターンに関するサンプル プロジェクトについては、こちらをご覧ください。
これは、フラグメントの構造によって異なります。フラグメント クラス B のいくつかのメソッドを静的にし、ターゲットの TextView オブジェクトも静的にできる場合は、フラグメント クラス A でメソッドを直接呼び出すことができます。これは、メソッドが瞬時に実行されるため、リスナーよりも優れています。アクティビティ全体でリスニングを実行する追加のタスクが必要です。以下の例を参照してください。
Fragment_class_B.setmyText(String yourstring);
フラグメント B では、メソッドを次のように定義できます。
public static void setmyText(final String string) {
myTextView.setText(string);
}
フラグメント B で myTextView を static に設定し、フラグメント A でフラグメント B クラスを適切にインポートすることを忘れないでください。
最近私のプロジェクトで手順を実行したところ、うまくいきました。それが役に立ったことを願っています。
このドキュメントを読むことができます。この概念はここでよく説明されていますhttp://developer.android.com/training/basics/fragments/communicating.html
基本的に Activity と Fragment 間の通信を行うためのインターフェースを実装します。
1) 主な活動
public class MainActivity extends Activity implements SendFragment.StartCommunication
{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public void setComm(String msg) {
// TODO Auto-generated method stub
DisplayFragment mDisplayFragment = (DisplayFragment)getFragmentManager().findFragmentById(R.id.fragment2);
if(mDisplayFragment != null && mDisplayFragment.isInLayout())
{
mDisplayFragment.setText(msg);
}
else
{
Toast.makeText(this, "Error Sending Message", Toast.LENGTH_SHORT).show();
}
}
}
2) 送信者フラグメント (フラグメントからアクティビティへ)
public class SendFragment extends Fragment
{
StartCommunication mStartCommunicationListner;
String msg = "hi";
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View mView = (View) inflater.inflate(R.layout.send_fragment, container);
final EditText mEditText = (EditText)mView.findViewById(R.id.editText1);
Button mButton = (Button) mView.findViewById(R.id.button1);
mButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
msg = mEditText.getText().toString();
sendMessage();
}
});
return mView;
}
interface StartCommunication
{
public void setComm(String msg);
}
@Override
public void onAttach(Activity activity) {
// TODO Auto-generated method stub
super.onAttach(activity);
if(activity instanceof StartCommunication)
{
mStartCommunicationListner = (StartCommunication)activity;
}
else
throw new ClassCastException();
}
public void sendMessage()
{
mStartCommunicationListner.setComm(msg);
}
}
3) 受信側フラグメント (Activity-to-fragment)
public class DisplayFragment extends Fragment
{
View mView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
mView = (View) inflater.inflate(R.layout.display_frgmt_layout, container);
return mView;
}
void setText(String msg)
{
TextView mTextView = (TextView) mView.findViewById(R.id.textView1);
mTextView.setText(msg);
}
}
私はこのリンクを同じ解決策に使用しました。誰かが役に立つことを願っています。非常に単純で基本的な例。
http://infobloggall.com/2014/06/22/communication-between-activity-and-fragments/
基本的に、ここではフラグメント間の通信を扱っています。フラグメント間の通信が直接可能になることは決してありません。これには、両方のフラグメントが作成されるコンテキストの下でのアクティビティが含まれます。
送信フラグメントにインターフェイスを作成し、アクティビティにインターフェイスを実装して、メッセージを受け取り、受信フラグメントに転送する必要があります。