2

AnActivity包含 a Fragment,后者又包含一个 child Fragment,它请求 a Service。该应用程序尝试实现dobjanschi休息架构。

完成Service工作后,它必须传播操作结果。我尝试使用 a PendingIntent但它似乎只被活动捕获,而我需要子片段来获得通知。你有什么建议吗?粘合剂?greenRobot 事件总线?RxJava(我在项目中已经有了)?

谢谢。

4

6 回答 6

6

RxJava

一种简单的方法是使用单例来包装同步的“PublishSubject”

 * Singleton
 * 
 * to send an event use EventBusRx.getInstance().topic1.onNext("completed");
 */
public class EventBusRx {
    private static EventBusRx ourInstance = new EventBusRx();
    public static EventBusRx getInstance() {
        return ourInstance;
    }
    private EventBusRx() {}

    /**
     * Use of multiple topics can be usefull
     * SerializedSubject avoid concurrency issues
     */
    public final Subject<String, String> topic1 = new SerializedSubject<>(PublishSubject.create());
    public final Subject<Integer, Integer> topic2 = new SerializedSubject<>(PublishSubject.create());
}

您可以从服务发送事件

EventBusRx.getInstance().topic1.onNext("completed");

并在片段中或随时响应事件

public class MyFragment extends Fragment {

    // [...]

    Subscription subscription_topic1;

    @Override
    public void onResume() {
        super.onResume();

        subscription_topic1 = EventBusRx.getInstance().topic2
                .subscribeOn(AndroidSchedulers.mainThread()) // or on other sheduler
                .subscribe(new Action1<Integer>() {
                    @Override
                    public void call(Integer integer) {
                        // update ui
                    }
                });
    }

    @Override
    public void onPause() {
        // important to avoid memory leaks
        subscription_topic1.unsubscribe();
        super.onPause();
    }
}

不要忘记取消订阅

这个想法类似于 Roger'one 使用单例但强制 ThreadSafety 包装 PublishSubject。

不需要 Observable.switchOnNext(subject)

事件总线库

greenRobot Eventbus 和 Otto 很好,并且具有相同的功能,但缺点是它们使连接更加冒烟(特别是 EventBus)。如果您已经使用 rx,我认为最好继续使用它

这是一篇关于 使用 RxJava 实现事件总线主题的令人兴奋的文章

本地广播

执行此操作的经典方法是使用LocalBroadcastManager但在我看来它们很痛苦

于 2015-11-07T22:43:36.627 回答
0

我目前正在开发一个完全基于 RxJava 的总线。由于您的项目中已经有 RxJava,因此您可以使用它。您应该使用 BehaviorSubject 和 Observable.switchOnNext()。

例如:

private BehaviorSubject<Observable<Whatever>> subject = BehaviorSubject.create();

public void post(){
    subject.onNext(...);
}

public Observable<Whatever> subscribe(){
    return Observable.switchOnNext(subject);
}

您应该将其作为 Singleton 的一部分,以便使用相同的 BehaviorSubject。您所要做的就是从一个片段发布()并在另一个片段或任何其他感兴趣的片段或活动中订阅()。您可以拥有任意数量的订阅,而且如果您正确实现它,那么最后发出的 Observable 将在方向更改后继续存在。

更多关于 BehaviorSubject 的信息可以在这里找到:https ://github.com/ReactiveX/RxJava/wiki/Subject

于 2014-10-03T23:08:18.517 回答
0

我目前正在将此 Pub/Sub 模式与 rxjava 和 enum 类一起使用。

public enum Events {

  public static PublishSubject <Object> myEvent = PublishSubject.create ();
}

//你想在哪里发布东西

Events.myEvent.onNext(myObject);

//你想在哪里接收事件

Events.myEvent.subscribe (...); 
于 2014-10-06T01:07:11.333 回答
0

我建议对这类事情使用事件总线。它将允许您向系统内的组件发送消息,而无需创建特殊的处理程序。

Otto 是一个流行的开源库,还有其他的。http://square.github.io/otto/

于 2014-10-01T11:55:31.913 回答
0

试试这个方法希望对你有帮助。

例如:

您的服务

public class MyService extends Service{

    public static MyServiceListener getMyServiceListener() {
        return MyService.myServiceListener;
    }

    public static void setMyServiceListener(MyServiceListener myServiceListener) {
        MyService.myServiceListener = myServiceListener;
    }

    private static MyServiceListener myServiceListener;


    public interface MyServiceListener{
        void onResult(String response);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();


    }

    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        executeYourTask();
    }

    private void executeYourTask(){

        String result = "SomeResultMaybeFromServer";

        if(getMyServiceListener()!=null){
            getMyServiceListener().onResult(result);
        }
    }
}

你的片段

    public class MyFragment extends Fragment {




    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {


        View v = null; // some view

        // Start service


        MyService.setMyServiceListener(new MyService.MyServiceListener() {
            @Override
            public void onResult(String response) {

                getActivity().runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        // To handle memory/window leaks
                    }
                });

            }
        });

        return v;
    }
}
于 2014-10-01T11:45:12.910 回答
0

我会使用基于 rx 的事件总线。将其设为单音并订阅特定的类类型。

public class RxBus {
    private static final RxBus sBus = new RxBus();
    private final Subject<Object, Object> mBus = new SerializedSubject<>(PublishSubject.create());

    private RxBus() {
    }

    public static RxBus getInstance() {
        return sBus;
    }

    public void send(Object o) {
        mBus.onNext(o);
    }

    public Observable<Object> observe() {
        return mBus;
    }

    @SuppressWarnings("unchecked")
    public <T> Observable<T> observe(Class<T> c) {
        return mBus.filter(o -> c.isAssignableFrom(o.getClass())).map(o -> (T) o);
    }
}

用法:

class Message { public String result};

发送一个消息:

Message m = new Message();
m.result = "Hello world";
RxBus.getInstance().send(m);

订阅特定的类类型:

RxBus.getInstance().observe(Message.class).subscribe(msg -> Log.e(TAG, "Message was caught : " + msg));
于 2015-11-09T19:51:08.630 回答