Android中嵌套片段之间的通信

我最近学会了如何在Android中制作嵌套的片段 。 不过,我不知道沟通应该如何发生。

在这里输入图像说明

从阅读片段通信文档,我知道这一点

所有片段到片段的通信都是通过关联的活动完成的。 两个碎片不应该直接沟通。

这对于活动中的同胞片段是有意义的,但是对于父母 – 孩子片段交stream没有多大意义。 我是否需要一直到活动只为儿童片段与父母的片段? 如果答案是一个简单的“是”,那么我可以做到这一点。 如果是“否”,那么代码devise会是什么样子?

我在Nested Fragment文档中看到,可以使用getParentFragment()来获取父片段的引用。 那么这是否意味着孩子应该直接与父母沟通? 这与正常片段与父活动进行通信所鼓励的情况相反。

Solutions Collecting From Web of "Android中嵌套片段之间的通信"

按照Rahul Sharma在评论中的build议,我使用接口callback来从Child Fragment传递给Parent Fragment和Activity。 我也把这个答案提交给代码评审 。 在这里,我正在采取非答案(在撰写本文的时候),表示这种devise模式没有大的问题。 在我看来,这与官方片段通讯文件中给出的一般指导是一致的。

示例项目

下面的示例项目扩展了问题中给出的示例。 它具有button,可以启动从片段到活动以及从子片段到父片段的向上通信。

我设置了这样的项目布局:

在这里输入图像说明

主要活动

该Activity从两个片段实现侦听器,以便它可以从中获取消息。

可选TODO:如果活动想要启动与片段的通信,则可以直接引用它们,然后调用其公共方法之一。

 import android.support.v4.app.FragmentTransaction; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; public class MainActivity extends AppCompatActivity implements ParentFragment.OnFragmentInteractionListener, ChildFragment.OnChildFragmentToActivityInteractionListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.replace(R.id.parent_fragment_container, new ParentFragment()); ft.commit(); } @Override public void messageFromParentFragmentToActivity(String myString) { Log.i("TAG", myString); } @Override public void messageFromChildFragmentToActivity(String myString) { Log.i("TAG", myString); } } 

家长片段

Parent Fragment实现了来自Child Fragment的侦听器,以便它可以从中接收消息。

可选的TODO:如果家长片段想要发起与儿童片段的沟通,可以直接引用它,然后调用其公共方法之一。

 import android.content.Context; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentTransaction; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; public class ParentFragment extends Fragment implements View.OnClickListener, ChildFragment.OnChildFragmentInteractionListener { // **************** start interesting part ************************ private OnFragmentInteractionListener mListener; @Override public void onClick(View v) { mListener.messageFromParentFragmentToActivity("I am the parent fragment."); } @Override public void messageFromChildToParent(String myString) { Log.i("TAG", myString); } public interface OnFragmentInteractionListener { void messageFromParentFragmentToActivity(String myString); } // **************** end interesting part ************************ @Override public void onAttach(Context context) { super.onAttach(context); if (context instanceof OnFragmentInteractionListener) { mListener = (OnFragmentInteractionListener) context; } else { throw new RuntimeException(context.toString() + " must implement OnFragmentInteractionListener"); } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_parent, container, false); view.findViewById(R.id.parent_fragment_button).setOnClickListener(this); return view; } @Override public void onViewCreated(View view, Bundle savedInstanceState) { Fragment childFragment = new ChildFragment(); FragmentTransaction transaction = getChildFragmentManager().beginTransaction(); transaction.replace(R.id.child_fragment_container, childFragment).commit(); } @Override public void onDetach() { super.onDetach(); mListener = null; } } 

儿童片段

Child Fragment定义了Activity和Parent Fragment的监听器接口。 如果子片段只需要与其中一个进行通信,则可以删除其他接口。

 import android.content.Context; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; public class ChildFragment extends Fragment implements View.OnClickListener { // **************** start interesting part ************************ private OnChildFragmentToActivityInteractionListener mActivityListener; private OnChildFragmentInteractionListener mParentListener; @Override public void onClick(View v) { switch (v.getId()) { case R.id.child_fragment_contact_activity_button: mActivityListener.messageFromChildFragmentToActivity("Hello, Activity. I am the child fragment."); break; case R.id.child_fragment_contact_parent_button: mParentListener.messageFromChildToParent("Hello, parent. I am your child."); break; } } public interface OnChildFragmentToActivityInteractionListener { void messageFromChildFragmentToActivity(String myString); } public interface OnChildFragmentInteractionListener { void messageFromChildToParent(String myString); } @Override public void onAttach(Context context) { super.onAttach(context); // check if Activity implements listener if (context instanceof OnChildFragmentToActivityInteractionListener) { mActivityListener = (OnChildFragmentToActivityInteractionListener) context; } else { throw new RuntimeException(context.toString() + " must implement OnChildFragmentToActivityInteractionListener"); } // check if parent Fragment implements listener if (getParentFragment() instanceof OnChildFragmentInteractionListener) { mParentListener = (OnChildFragmentInteractionListener) getParentFragment(); } else { throw new RuntimeException("The parent fragment must implement OnChildFragmentInteractionListener"); } } // **************** end interesting part ************************ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_child, container, false); view.findViewById(R.id.child_fragment_contact_activity_button).setOnClickListener(this); view.findViewById(R.id.child_fragment_contact_parent_button).setOnClickListener(this); return view; } @Override public void onDetach() { super.onDetach(); mActivityListener = null; mParentListener = null; } } 

尽pipe@ Suragch的答案是正确的,但我想添加另一种方式来传递FragmentsActivity之间的数据。 无论是Activity还是Fragment您都可以通过以下三个步骤将数据与事件总线进行传递:

1-定义一个事件(消息):

 public class OrderMessage { private final long orderId; /* Additional fields if needed */ public OrderMessage(long orderId) { this.orderId = orderId; } public long getOrderId() { return orderId; } } 

2-注册和注销事件:为了能够接收事件,类必须注册/注销事件总线。 ActivitiesFragments的最佳位置是onStart()onStop()

 @Override public void onStart() { super.onStart(); EventBus.getDefault().register(this); } @Override public void onStop() { EventBus.getDefault().unregister(this); super.onStop(); } 

为了能够收到一个事件,你必须订阅这个事件。 为此,请将@Subscribe注释添加到您的类中的某个方法中。

 @Subscribe(threadMode = ThreadMode.MAIN) public void onMessage(OrderMessage message){ /* Do something for example: */ getContractDetails(message.getOrderId()); } 

3-发布活动

 EventBus.getDefault().post(new OrderMessage(recievedDataFromWeb.getOrderId())); 

更多的文档和例子可以在这里find。 还有其他类似的图书馆: Otto