服务 - 片段沟通

时间:2014-10-01 11:12:38

标签: android android-intent android-service rx-java greenrobot-eventbus

Activity包含Fragment,而Fragment又包含一个Service子请求Service。该应用尝试实施dobjanschi休息架构。

PendingIntent完成工作时,它必须传播操作结果。我尝试使用{{1}},但它似乎只被活动捕获,而我需要子片段才能得到通知。你能提出什么建议吗?活页夹? greenRobot Eventbus? RxJava(我在项目中已有)?

感谢。

6 个答案:

答案 0 :(得分:6)

RxJava

一种简单的方法是使用Singleton来包装同步的'PostSubject'

 * 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)

EventBus Libraries

greenRobot Eventbus和Otto很不错并具有相同的功能,但缺点是它们使连接更加烟雾(特别是EventBus)。如果你已经使用rx我觉得最好还是坚持下去

这是一篇关于该主题的文章 Implementing an Event Bus With RxJava

LocalBroadcast

这样做的经典方法是使用LocalBroadcastManager,但在我的意见中,他们是痛苦的

答案 1 :(得分:0)

试试这种方式希望它可以帮助你。

例如:

<强> YourService

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);
        }
    }
}

<强> YourFragment

    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;
    }
}

答案 2 :(得分:0)

我建议使用事件总线进行此类操作。它允许您向系统中的组件发送消息,而无需创建特殊的处理程序。

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

答案 3 :(得分: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。您所要做的就是从一个片段发布post(),在另一个片段或任何其他感兴趣的片段或活动中订阅()。你可以拥有任意数量的订阅,如果你正确实现它,那么最后发出的Observable将会在方向更改后继续存在。

有关BehaviorSubject的更多信息,请访问:https://github.com/ReactiveX/RxJava/wiki/Subject

答案 4 :(得分:0)

我目前正在使用此发布/订阅模式与rxjava和枚举类。

public enum Events {

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

//你要发布的东西

Events.myEvent.onNext(myObject);

//您希望收到活动的地方

Events.myEvent.subscribe (...); 

答案 5 :(得分:0)

我会使用基于rx的事件总线。 将此作为sigletone并订阅特定的类类型。

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));