如何在碎片之间传递数据

我试图在我的程序中两个fragmens之间传递数据。 它只是一个存储在列表中的简单字符串。 列表是在片段A中公开的,当用户点击一个列表项时,我需要它在片段B中出现。内容提供者似乎只支持ID,所以这是行不通的。 有什么建议么?

我认为片段之间的交流应该通过活动来完成。 片段和活动之间的交流可以这样完成: https : //developer.android.com/training/basics/fragments/communicating.html https://developer.android.com/guide/components/fragments.html#CommunicatingWithActivity

如果您使用Roboguice,则可以使用Roboguice中的EventManager传递数据而不使用Activity作为接口。 这是相当干净的海事组织。

如果您不使用Roboguice,则可以使用Otto作为事件总线: http ://square.github.com/otto/

更新20150909:您现在也可以使用绿色机器人事件总线甚至RxJava。 取决于你的用例。

Fragment 文档 :

通常你会想要一个片段与另一个片段进行通信,例如根据用户事件来改变内容。 所有片段到片段的通信都是通过关联的活动完成的。 两个碎片不应该直接沟通。

所以我建议你看文档中的基本片段培训文档。 他们非常全面的例子和一个步行指南。

你为什么不使用捆绑。 从你的第一个片段,下面是如何设置它:

 Fragment fragment = new Fragment(); Bundle bundle = new Bundle(); bundle.putInt(key, value); fragment.setArguments(bundle); 

然后在你的第二个片段中,使用以下命令检索数据:

 Bundle bundle = this.getArguments(); int myInt = bundle.getInt(key, defaultValue); 

Bundle已经为很多数据类型提供了方法。 请参阅http://developer.android.com/reference/android/os/Bundle.html

所以可以说你有活动AB控制碎片A和碎片B.碎片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) { } }; 

回调接口放在你的片段之一(比如片段A)。 我认为这个Callbacks接口的目的就像任何Activity可以实现的Frag A里面的嵌套类。 因此,如果片段A是电视,则回调是电视遥控(接口),允许活动AB使用片段A. 我可能是错误的细节,因为我是一个noob,但我确实让我的程序在所有的屏幕尺寸上完美的工作,这就是我使用的。

所以在Fragment A中,我们有:(我从Android的Sample程序中获取这个)

 @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); } 

在Activity 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(); } 

所以在Activity AB中,你基本上把所有东西都扔进一个Bundle中,然后传递给B.如果你不确定如何使用Bundle,那么就看看这个类。

我基本上是由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-注册/取消注册到事件总线

 @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-订阅该事件以在您的Fragment中接收它

 @Subscribe(threadMode = ThreadMode.MAIN) public void onMessage(Message event){ mytextview.setText(event.message); } 

有关更多详细信息,用例以及关于事件总线模式的示例项目 。

这取决于片段的结构。 如果可以在Fragment Class B静态方法上使用某些方法,并且目标TextView对象是静态方法,则可以直接在Fragment Class A上调用方法。由于该方法是瞬间执行的,因此比侦听器更好,不需要在整个活动中执行一个额外的任务。 看下面的例子:

 Fragment_class_B.setmyText(String yourstring); 

在片段B上,您可以将方法定义为:

 public static void setmyText(final String string) { myTextView.setText(string); } 

只要不要忘记在分片B上将myTextView设置为静态,并正确导入分片A上的分片B类。

刚刚在我的项目上做了最近的程序,它的工作。 希望有所帮助。

你可以阅读这个文件。这个概念很好的解释在这里http://developer.android.com/training/basics/fragments/communicating.html

我正在做一个类似的项目,我想我的代码可能有助于上述情况

这是我在做什么的概述

我的项目有两个片段叫做“ FragmentA ”和“FragmentB

FragmentA包含一个列表视图,当你点击FragmentA中的一个项目时它的INDEX被传递给使用Communicator接口的FragmentB

  • 设计模式完全基于java接口的概念,即“ 接口引用变量可以引用子类对象”
  • MainActivity实现由fragmentA提供的接口(否则我们不能使接口引用变量指向MainActivity)
  • 在下面的代码中,通过使用fragmentA中的setCommunicator(Communicatot c) ”方法来引用MainActivity的对象。
  • 我使用MainActivity的引用触发FrgamentA的接口的respond()方法。

    接口通信器是在fragmentA内部定义的,这是为了给通信器接口提供最少的访问权限。

以下是我的完整工作代码

FragmentA.java

 public class FragmentA extends Fragment implements OnItemClickListener { ListView list; Communicator communicater; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // TODO Auto-generated method stub return inflater.inflate(R.layout.fragmenta, container,false); } public void setCommunicator(Communicator c){ communicater=c; } @Override public void onActivityCreated(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onActivityCreated(savedInstanceState); communicater=(Communicator) getActivity(); list = (ListView) getActivity().findViewById(R.id.lvModularListView); ArrayAdapter<?> adapter = ArrayAdapter.createFromResource(getActivity(), R.array.items, android.R.layout.simple_list_item_1); list.setAdapter(adapter); list.setOnItemClickListener(this); } @Override public void onItemClick(AdapterView<?> arg0, View arg1, int index, long arg3) { communicater.respond(index); } public interface Communicator{ public void respond(int index); } 

}

fragmentB.java

 public class FragmentA extends Fragment implements OnItemClickListener { ListView list; Communicator communicater; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // TODO Auto-generated method stub return inflater.inflate(R.layout.fragmenta, container,false); } public void setCommunicator(Communicator c){ communicater=c; } @Override public void onActivityCreated(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onActivityCreated(savedInstanceState); communicater=(Communicator) getActivity(); list = (ListView) getActivity().findViewById(R.id.lvModularListView); ArrayAdapter<?> adapter = ArrayAdapter.createFromResource(getActivity(), R.array.items, android.R.layout.simple_list_item_1); list.setAdapter(adapter); list.setOnItemClickListener(this); } @Override public void onItemClick(AdapterView<?> arg0, View arg1, int index, long arg3) { communicater.respond(index); } public interface Communicator{ public void respond(int index); } } 

MainActivity.java

 public class MainActivity extends Activity implements FragmentA.Communicator { FragmentManager manager=getFragmentManager(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); FragmentA fragA=(FragmentA) manager.findFragmentById(R.id.fragmenta); fragA.setCommunicator(this); } @Override public void respond(int i) { // TODO Auto-generated method stub FragmentB FragB=(FragmentB) manager.findFragmentById(R.id.fragmentb); FragB.changetext(i); } } 

基本上实现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/

在我的情况下,我不得不从FragmentB-> FragmentA向后发送数据,因此Intents不是一个选项,因为这个片段已经被初始化了 。虽然所有上述答案听起来不错,但是需要很多的锅炉代码才能实现 ,所以我用一个更简单的方法来使用LocalBroadcastManager ,它完全符合上述说法,但没有alll讨厌的样板代码。 下面分享一个例子。

发送片段(片段B)

 public class FragmentB { private void sendMessage() { Intent intent = new Intent("custom-event-name"); intent.putExtra("message", "your message"); LocalBroadcastManager.getInstance(this).sendBroadcast(intent); } } 

并在消息接收片段(片段A)

  public class FragmentA { @Override public void onCreate(Bundle savedInstanceState) { ... // Register receiver LocalBroadcastManager.getInstance(this).registerReceiver(receiver, new IntentFilter("custom-event-name")); } // This will be called whenever an Intent with an action named "custom-event-name" is broadcasted. private BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String message = intent.getStringExtra("message"); } }; } 

希望它可以帮助别人

片段类A

 public class CountryListFragment extends ListFragment{ /** List of countries to be displayed in the ListFragment */ ListFragmentItemClickListener ifaceItemClickListener; /** An interface for defining the callback method */ public interface ListFragmentItemClickListener { /** This method will be invoked when an item in the ListFragment is clicked */ void onListFragmentItemClick(int position); } /** A callback function, executed when this fragment is attached to an activity */ @Override public void onAttach(Activity activity) { super.onAttach(activity); try{ /** This statement ensures that the hosting activity implements ListFragmentItemClickListener */ ifaceItemClickListener = (ListFragmentItemClickListener) activity; }catch(Exception e){ Toast.makeText(activity.getBaseContext(), "Exception",Toast.LENGTH_SHORT).show(); } } 

片段B类

 public class CountryDetailsFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { /** Inflating the layout country_details_fragment_layout to the view object v */ View v = inflater.inflate(R.layout.country_details_fragment_layout, null); /** Getting the textview object of the layout to set the details */ TextView tv = (TextView) v.findViewById(R.id.country_details); /** Getting the bundle object passed from MainActivity ( in Landscape mode ) or from * CountryDetailsActivity ( in Portrait Mode ) * */ Bundle b = getArguments(); /** Getting the clicked item's position and setting corresponding details in the textview of the detailed fragment */ tv.setText("Details of " + Country.name[b.getInt("position")]); return v; } } 

用于在片段之间传递数据的主要Activity类

 public class MainActivity extends Activity implements ListFragmentItemClickListener { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } /** This method will be executed when the user clicks on an item in the listview */ @Override public void onListFragmentItemClick(int position) { /** Getting the orientation ( Landscape or Portrait ) of the screen */ int orientation = getResources().getConfiguration().orientation; /** Landscape Mode */ if(orientation == Configuration.ORIENTATION_LANDSCAPE ){ /** Getting the fragment manager for fragment related operations */ FragmentManager fragmentManager = getFragmentManager(); /** Getting the fragmenttransaction object, which can be used to add, remove or replace a fragment */ FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); /** Getting the existing detailed fragment object, if it already exists. * The fragment object is retrieved by its tag name * */ Fragment prevFrag = fragmentManager.findFragmentByTag("in.wptrafficanalyzer.country.details"); /** Remove the existing detailed fragment object if it exists */ if(prevFrag!=null) fragmentTransaction.remove(prevFrag); /** Instantiating the fragment CountryDetailsFragment */ CountryDetailsFragment fragment = new CountryDetailsFragment(); /** Creating a bundle object to pass the data(the clicked item's position) from the activity to the fragment */ Bundle b = new Bundle(); /** Setting the data to the bundle object */ b.putInt("position", position); /** Setting the bundle object to the fragment */ fragment.setArguments(b); /** Adding the fragment to the fragment transaction */ fragmentTransaction.add(R.id.detail_fragment_container, fragment,"in.wptrafficanalyzer.country.details"); /** Adding this transaction to backstack */ fragmentTransaction.addToBackStack(null); /** Making this transaction in effect */ fragmentTransaction.commit(); }else{ /** Portrait Mode or Square mode */ /** Creating an intent object to start the CountryDetailsActivity */ Intent intent = new Intent("in.wptrafficanalyzer.CountryDetailsActivity"); /** Setting data ( the clicked item's position ) to this intent */ intent.putExtra("position", position); /** Starting the activity by passing the implicit intent */ startActivity(intent); } } } 

详细的活动类

 public class CountryDetailsActivity extends Activity{ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); /** Setting the layout for this activity */ setContentView(R.layout.country_details_activity_layout); /** Getting the fragment manager for fragment related operations */ FragmentManager fragmentManager = getFragmentManager(); /** Getting the fragmenttransaction object, which can be used to add, remove or replace a fragment */ FragmentTransaction fragmentTransacton = fragmentManager.beginTransaction(); /** Instantiating the fragment CountryDetailsFragment */ CountryDetailsFragment detailsFragment = new CountryDetailsFragment(); /** Creating a bundle object to pass the data(the clicked item's position) from the activity to the fragment */ Bundle b = new Bundle(); /** Setting the data to the bundle object from the Intent*/ b.putInt("position", getIntent().getIntExtra("position", 0)); /** Setting the bundle object to the fragment */ detailsFragment.setArguments(b); /** Adding the fragment to the fragment transaction */ fragmentTransacton.add(R.id.country_details_fragment_container, detailsFragment); /** Making this transaction in effect */ fragmentTransacton.commit(); } } 

一系列的Contries

 public class Country { /** Array of countries used to display in CountryListFragment */ static String name[] = new String[] { "India", "Pakistan", "Sri Lanka", "China", "Bangladesh", "Nepal", "Afghanistan", "North Korea", "South Korea", "Japan", "Bhutan" }; } 

欲了解更多详情,请访问此链接[ http://wptrafficanalyzer.in/blog/itemclick-handler-for-listfragment-in-android/%5D 。 有完整的例子..

基本上这里我们正在处理碎片之间的通信。 片段之间的通信永远不可能直接进行。 它涉及在这两个片段都被创建的情况下的活动。

您需要在发送的分片中创建一个接口,并在活动中实现接口,这将缓存消息并传输到接收片段。