使用RxJava在Android中从Activity更新片段

17

我有一个简单的用例:

  • Activity1创建Fragment1。

  • 在创建Fragment1后,Fragment1会通知Activity1它已经被创建,并更新其Activity1视图。

  • Activity1在收到通知后会更新Fragment1的视图。

我正在使用RxAndroid、子库rxlifecycle组件和Android,但我仍处于学习阶段,StackOverflow上甚至没有rx-lifecycle标签,所以我仍在努力理解此库的流程...

编辑

我更喜欢不使用EventBus,它就像每个人都在向每个人大喊要做什么一样,因此Rxjava Observable方法会更有用。


你为什么想让Activity调用Fragment函数?你具体在做什么? - OneCricketeer
这只是一个使用案例,我基本上在活动中进行网络调用,完成后在地图片段中绘制折线,该片段是单独的片段,替换了活动的帧布局,但问题是生命周期,我不知道何时片段会被创建,因此我无法在片段中获取空上下文。 - Zulqurnain Jutt
你可以使用 onAttach 方法来获取 Context/Activity 的引用,并调用任何方法,或者你可以在 Fragment 中完全处理网络请求。不过我对 Rx 相关的东西不太确定。 - OneCricketeer
EventBus 可能在这种情况下很有用。 - ugur
在我提到的问题中,我必须更改片段和活动的视图,这现在非常难以处理。在RxJava中,我认为应该有更好的方法来解决这个问题。 - Zulqurnain Jutt
2个回答

6
考虑以下两点:
  1. 使用EventBus并不意味着它必须是全局的。如果需要,您可以拥有多个事件总线,并且可以在两个组件(Activity和Fragment)之间共享单个事件总线。

  2. RxJava文档中有几个示例展示了如何使用RxJava实现事件总线功能。

通过使用事件总线,您可以将整个过程与Android生命周期分离,从而大大简化事情。


我非常讨厌EventBus的一件事情就是它只监听单个对象类型,那么如果我需要在某个特定事件上进行通信,比如在Activity上点击可能会导致在Fragment中更新视图,基本上就是将字符串传递给Fragment和Activity之间互相传递,这只能意味着我必须创建两个单独的类,才能使用EventBus实现这种通信! - Zulqurnain Jutt
2
或者你可以接收一些BaseEvent,其中包含事件类型,然后使用“命令”设计模式 - 将该事件的处理程序存储在映射中,取出正确的处理程序并处理该事件。我在重构代码时必须这样做一次。 - Alex Shutov

6

如果要将片段中的信息发布到活动中,您应该使用事件总线来通知活动有关片段创建的信息(替换回调和它们所创建的混乱)。

使用RxJava的事件总线示例代码如下:

public class SampleEventsBus {
    private static final String TAG = SampleEventsBus.class.getSimpleName();
    private static final String TAG2 = SampleEventsBus.class.getCanonicalName();

    public static final int ACTION_FRAGMENT_CREATED = 1;
    public static final int ACTION_FRAGMENT_OTHER = 2;

    private static SampleEventsBus mInstance;

    public static SampleEventsBus getInstance() {
        if (mInstance == null) {
            mInstance = new SampleEventsBus();
        }
        return mInstance;
    }

    private SampleEventBus() {}

    private PublishSubject<Integer> fragmentEventSubject = PublishSubject.create();

    public Observable<Integer> getFragmentEventObservable() {
        return fragmentEventSubject;
    }

    public void postFragmentAction(Integer actionId) {
        fragmentEventSubject.onNext(actionId);
    }
}

然后从您的片段中,您可以调用以下内容:
SampleEventsBus.getInstance().postFragmentAction(SampleEventsBus.ACTION_FRAGMENT_CREATED);

你可以在onAttach()onViewCreated()或其他任何你喜欢的地方添加以下代码。

此外,在活动中,你需要添加以下代码来监听你的事件总线:

SampleEventsBus .getInstance().getFragmentEventObservable().subscribe(new Subscriber<Integer>() {
        @Override
        public void onCompleted() {

        }

        @Override
        public void onError(Throwable e) {

        }

        @Override
        public void onNext(Integer actionId) {
            if(actionId == SampleEventsBus.ACTION_FRAGMENT_CREATED) {
                //do any required action
            }
        }
    });

对于第二部分,即从活动中更新片段,我不建议使用此方法,因为它会导致不必要的复杂性,而应该使用“原始方式”:

  1. 在Fragment中创建一个名为updateView(Object obj)的方法
  2. onNext()中,获取所需的片段:SampleFragment fragment = (SampleFragment)getSupportFragmentManager().findFragmentByTag("TAG");
  3. 调用fragment.updateView(obj);

希望这能帮到您。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接