AnActivity
包含 a Fragment
,后者又包含一个 child Fragment
,它请求 a Service
。该应用程序尝试实现dobjanschi休息架构。
完成Service
工作后,它必须传播操作结果。我尝试使用 a PendingIntent
但它似乎只被活动捕获,而我需要子片段来获得通知。你有什么建议吗?粘合剂?greenRobot 事件总线?RxJava(我在项目中已经有了)?
谢谢。
AnActivity
包含 a Fragment
,后者又包含一个 child Fragment
,它请求 a Service
。该应用程序尝试实现dobjanschi休息架构。
完成Service
工作后,它必须传播操作结果。我尝试使用 a PendingIntent
但它似乎只被活动捕获,而我需要子片段来获得通知。你有什么建议吗?粘合剂?greenRobot 事件总线?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但在我看来它们很痛苦
我目前正在开发一个完全基于 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
我目前正在将此 Pub/Sub 模式与 rxjava 和 enum 类一起使用。
public enum Events {
public static PublishSubject <Object> myEvent = PublishSubject.create ();
}
//你想在哪里发布东西
Events.myEvent.onNext(myObject);
//你想在哪里接收事件
Events.myEvent.subscribe (...);
我建议对这类事情使用事件总线。它将允许您向系统内的组件发送消息,而无需创建特殊的处理程序。
Otto 是一个流行的开源库,还有其他的。http://square.github.io/otto/
试试这个方法希望对你有帮助。
例如:
您的服务
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;
}
}
我会使用基于 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));