【问题标题】:Communicate between different instances of same fragment在同一片段的不同实例之间进行通信
【发布时间】:2016-03-15 23:02:29
【问题描述】:

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

  • 标签 1(片段 A)。需要将数据发送到 Tab 2。
  • 标签 2(片段 B)。需要从 Tab 1 接收数据。
  • 标签 3(片段 B)。已经包含数据。

如您所见,Tab 3 和 Tab 2 包含相同的 Fragment 但不同的实例。

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

我尝试过的:

  1. 在创建片段 B 时通过参数设置其唯一 ID。
  2. 为 Fragment B 的两个实例注册相同的 Local Broadcast Receiver
  3. 将数据从 Fragment A 发送到 Fragment B 及其 ID
  4. 在 Fragment B onReceive() 检查收到的 ID 是否等于 Fragment 的 ID

但不幸的是,广播仅发送到 Tab 3。


编辑:更多信息。

这些选项卡托管在另一个带有ViewPager 的片段中。那是由于NavigationDrawer 的组合,它具有与ViewPager 和相关标签的片段。

【问题讨论】:

  • 为什么不让fragment A给你的activity发送数据,让你的activity给你fragment B发送呢?
  • 你看,发送数据没有问题。问题是将数据完全发送到片段 B 的第一个实例
  • 我认为 BroadcastReceiver 占用太多内存并且是异步过程,我认为您不需要。它还有安全问题需要解决。

标签: android android-fragments tabs broadcastreceiver android-broadcast


【解决方案1】:

如果你从 Fragment A 移动到 Fragment B,你可以简单地将值传递给 Fragment B 的构造函数。

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

【讨论】:

  • 数据在运行时被多次传输。有一些事件触发的解决方案更好
【解决方案2】:

您可以使用 Bundle 的思想在 Fragment 之间传递数据。我可以看到我在之前的帖子中对这个想法的建议被误解了。 这是片段接收数据的示例代码。 片段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

Fragment2 recvfragment = Fragment2.newInstance(itemId, itemName);

注意事项:

  • 使用 Bundle,您可以将特定数据类型和值传递到您需要的不同片段实例中。
  • 在这种情况下,代码将 Long 和 String 类型传递给 Fragment2

【讨论】:

  • 如果你仔细看我的问题,你会发现通过参数传递的数据并不能让我满意,因为数据应该在已经创建片段的运行时传递
  • @AnZ,在我的示例中,您可以将特定值传递给 "newInstance(long param1..." 中的第一个参数。无论哪个片段是调用者,主要活动都可以将值传递给一个片段,然后该片段可以将值传递给接收片段。这是我的首选技术,因为它占用的内存更少。而且...我确实尝试仔细阅读您的帖子。
【解决方案3】:

你没有写下你是如何在运行时添加片段的。最好在运行时添加它并将 TAG 分配给每个片段,如下所示:

...
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")

希望它会有所帮助。

【讨论】:

    【解决方案4】:

    我建议在你的应用中引入EventBus

    要添加依赖项 - 将 compile '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() {}
    }
    

    在 Fragment A 中发送事件:

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

    (并且为了避免在第二个选项卡中处理事件 - 只需在片段实例化期间传递额外的参数,如果它必须监听事件)

    【讨论】:

    • 事件驱动开发,嗯?这是有趣的方法。打算试一试。谢谢!
    【解决方案5】:

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

    YourActivity implements MyInterface {
    ...
    }
    

    在你的片段中你定义了这个:

    @Override
    public void onAttach(final Activity context) {
      myInterface = (MyInterface) context;
    }
    

    当您单击片段中的某些内容时,请调用myInterface.doSomething(parameter);。然后您的活动可以委托给另一个片段。

    【讨论】:

    • 这是正确的做法!
    • 感谢您的快速回复。这些片段托管在一个片段中(因为我有带有片段的 NavigationDrawer,其中包含带有这些选项卡的 ViewPager)。但无论如何,我明白你的意思。打算试一试。
    • 很抱歉没有提供信息,但似乎这种方法不适用于片段中托管的片段。我在OnAttach() 中收到ClassCastException。将要编辑问题
    • 如果它们托管在 viewpager 中,您应该在 viewpager 适配器中处理这个问题。每个片段应该对应一个特定的位置,你可以更新你的片段。
    • @ThomasR.,我不太明白如何在适配器中使用接口。你能编辑你的答案给我一些提示吗?还是说不用接口也能实现?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-13
    • 2011-08-05
    • 1970-01-01
    • 2012-06-15
    • 1970-01-01
    相关资源
    最近更新 更多