Android 在同一片段的不同实例之间通信

Android 在同一片段的不同实例之间通信,android,android-fragments,tabs,broadcastreceiver,android-broadcast,Android,Android Fragments,Tabs,Broadcastreceiver,Android Broadcast,问题如下。让我们有3个带片段的选项卡: 表1(片段A)。需要将数据发送到选项卡2 表2(片段B)。需要从选项卡1接收数据 表3(片段B)。已包含数据 如您所见,选项卡3和选项卡2包含相同的片段,但实例不同 如何将数据(不是通过参数)发送到选项卡2? 我所尝试的: 创建片段B时,通过参数为其设置唯一ID 为片段B的两个实例注册相同的本地广播接收器 将数据从片段A发送到带有ID的片段B 在片段BonReceive()中,检查received ID是否等于片段的ID 但不幸的是,广播只发送到表3

问题如下。让我们有3个带片段的选项卡:

  • 表1(片段A)。需要将数据发送到选项卡2
  • 表2(片段B)。需要从选项卡1接收数据
  • 表3(片段B)。已包含数据
如您所见,选项卡3和选项卡2包含相同的片段,但实例不同

如何将数据(不是通过参数)发送到选项卡2?

我所尝试的:

  • 创建片段B时,通过参数为其设置唯一ID
  • 为片段B的两个实例注册相同的
    本地广播接收器
  • 将数据从片段A发送到带有ID的片段B
  • 在片段B
    onReceive()
    中,检查received ID是否等于片段的ID
  • 但不幸的是,广播只发送到表3


    编辑:更多信息


    这些选项卡位于另一个带有
    ViewPager
    的片段中。这是由于
    NavigationDrawer
    ViewPager
    的片段以及前面提到的选项卡的组合

    片段是否托管在一个活动中?然后,您可以在托管活动上实现一个接口

    YourActivity implements MyInterface {
    ...
    }
    
    在你的片段中,你定义了:

    @Override
    public void onAttach(final Activity context) {
      myInterface = (MyInterface) context;
    }
    
    当您单击片段中的某个内容时,然后调用
    myInterface.doSomething(参数)。然后你的活动可以委托给另一个片段。

    我建议在你的应用程序中介绍

    添加依赖项-将“de.greenrobot:eventbus:2.4.0”添加到依赖项列表中

    然后,您只需订阅第三个选项卡的片段,以侦听第一个片段中的事件

    类似这样的东西:在片段B中

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        eventBus.register(this);
    }
    
    @Override
    public void onDetach() {
        eventBus.unregister(this);
        super.onDetach();
    }
    
    @SuppressWarnings("unused") // invoked by EventBus
    public void onEventMainThread(NewDataEvent event) {
        // Handle new data
    }
    
    NewDataEvent.java

    public class NewDataEvent extends EventBase {
        public NewDataEvent() {}
    }
    
    在片段A中,只需发送事件:

    protected EventBus eventBus;
    ....
    eventBus = EventBus.getDefault();
    ....
    eventBus.post(new NewDataEvent());
    

    (为了避免在第二个选项卡中处理事件,只要在片段的实例化过程中传递额外的参数,如果它必须侦听事件)

    您没有写如何在运行时添加片段,或者不添加片段。最好在运行时添加它,并将标记分配给每个片段,如下所示:

    ...
    fragmentTransaction.replace(R.id.layoutTab2, fragment, "F-B-2");
    ...
    fragmentTransaction.replace(R.id.layoutTab3, fragment, "F-B-3");
    ...
    
    所以以后你们可以通过标签识别或找到片段。例如:

    FragmentManager.findFragmentByTag("F-B-2")
    
    或者,如果您需要片段B 3:

    FragmentManager.findFragmentByTag("F-B-3")
    

    希望能有所帮助。

    您可以使用Bundle的思想在片段之间传递数据。我可以看出我在前一篇文章中对这个想法的建议被误解了。 下面是片段接收数据的示例代码片段2

    public static Fragment2 newInstance(long param1, String param2) {
        MediaFragment fragment = new Fragment2();
        Bundle args = new Bundle();
    
        args.putLong(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
    
        fragment.setArguments(args);
        return fragment;
    }
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            Bundle bundle = getArguments();
            audioId = bundle.getLong(ARG_PARAM1);
            audioName = bundle.getString(ARG_PARAM2);
        }
    }
    
    Fragment2 recvfragment = Fragment2.newInstance(itemId, itemName);
    
    在另一个片段或活动上,调用片段2

    public static Fragment2 newInstance(long param1, String param2) {
        MediaFragment fragment = new Fragment2();
        Bundle args = new Bundle();
    
        args.putLong(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
    
        fragment.setArguments(args);
        return fragment;
    }
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            Bundle bundle = getArguments();
            audioId = bundle.getLong(ARG_PARAM1);
            audioName = bundle.getString(ARG_PARAM2);
        }
    }
    
    Fragment2 recvfragment = Fragment2.newInstance(itemId, itemName);
    
    注:

    • 使用bundle,您可以将特定的数据类型和值传递到片段的不同实例中,这是您所需要的
    • 在这种情况下,代码将一个长字符串类型传递到
      Fragment2

    如果要从片段A移动到片段B,只需将值传递给片段B的构造函数即可


    或者,如果您需要在所有三个片段中使用相同的数据集,也可以使用共享首选项。

    这是正确的方法!谢谢你的快速回复。这些片段托管在一个片段中(因为我有NavigationDrawer with fragment,其中包含带有这些选项卡的ViewPager)。但无论如何,我明白你的意思。我想试试。很抱歉取消通知,但这种方法似乎不适用于托管在片段中的片段。我在
    OnAttach()
    中收到
    ClassCastException
    。要编辑问题如果它们位于viewpager中,则应在viewpager适配器中处理此问题。每个片段都应该对应于一个特定的位置,您可以更新您的片段。@ThomasR.,我不太明白如何在适配器中使用接口。你能修改一下你的答案给我一些提示吗?或者没有接口就可以实现的perhabs?事件驱动开发,嗯?这是一个有趣的方法。我想试试看。非常感谢。为什么不让片段A向您的活动发送数据,让活动向您发送片段B?您知道,发送数据没有问题。问题是将数据准确地发送到Fragment BI think BroadcastReceiver的第一个实例会占用太多内存,而且是异步过程,我认为您不需要这样做。它还需要解决安全问题。数据在运行时传输,并多次传输。有一些事件触发的解决方案更好。如果您仔细看我的问题,您会发现通过参数传递的数据并不能满足我的要求,因为数据应该在运行时传递,而片段已经存在created@AnZ,在我的示例中,可以将特定值传递给“newInstance(long param1…”中的第一个参数。无论哪个片段是调用方,主活动都可以将值传递给片段,然后该片段可以将值传递给接收片段。这是我首选的技术,因为它占用的内存较少。而且……我确实仔细阅读了您的帖子。