Android 服务片段通信
Android 服务片段通信,android,android-intent,android-service,rx-java,greenrobot-eventbus,Android,Android Intent,Android Service,Rx Java,Greenrobot Eventbus,活动包含一个片段,该片段又包含一个子片段,该子片段请求一个服务。该应用程序尝试实现rest体系结构 当服务完成工作时,它必须传播操作结果。我尝试使用一个pendingent,但它似乎只被活动捕获,而我需要子片段得到通知。你有什么建议吗?粘合剂绿色巴士?RxJava(我在项目中已经有了) 谢谢。试试这个方法,希望对你有帮助 例如: 您的服务 public class MyService extends Service{ public static MyServiceListener ge
活动
包含一个片段
,该片段又包含一个子片段
,该子片段请求一个服务
。该应用程序尝试实现rest体系结构
当服务
完成工作时,它必须传播操作结果。我尝试使用一个pendingent
,但它似乎只被活动捕获,而我需要子片段得到通知。你有什么建议吗?粘合剂绿色巴士?RxJava(我在项目中已经有了)
谢谢。试试这个方法,希望对你有帮助 例如: 您的服务
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;
}
}
我建议使用事件总线来完成这类事情。它将允许您向系统中的组件发送消息,而无需创建特殊的处理程序
Otto是一个流行的开源库,还有其他一些 我目前正在开发一种完全基于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);
}
private BehaviorSubject subject=BehaviorSubject.create();
公共空缺职位(){
主题.onNext(…);
}
公共可观测订阅(){
返回可观察。开关下一个(主题);
}
您应该将其作为Singleton的一部分,以便使用相同的BehaviorSubject。您所要做的就是从一个片段发布()并在另一个片段或任何其他感兴趣的片段或活动中订阅()。您可以拥有任意数量的订阅,另外,如果您正确地实现了它,那么最后发出的可观察对象将在方向更改后仍然存在
关于BehaviorSubject的更多信息可以在这里找到:我目前正在rxjava和enum类中使用这个发布/订阅模式
public enum Events {
public static PublishSubject <Object> myEvent = PublishSubject.create ();
}
//您希望接收事件的位置
Events.myEvent.subscribe (...);
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());
}
并在片段中或任何需要的时候响应事件
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();
}
}
公共类MyFragment扩展了片段{
// [...]
认购主题1;
@凌驾
恢复时公开作废(){
super.onResume();
订阅\u topic1=EventBusRx.getInstance().topic2
.subscribeOn(AndroidSchedulers.mainThread())//或在其他调度程序上
.订阅(新操作1(){
@凌驾
公共无效调用(整数){
//更新用户界面
}
});
}
@凌驾
公共无效暂停(){
//避免内存泄漏非常重要
订阅主题1.取消订阅();
super.onPause();
}
}
不要忘记取消订阅
这个想法类似于Roger'one使用单例,但强制执行ThreadSafety包装主题
不需要可观察。switchOnNext(主题)
事件总线库
greenRobot Eventbus和Otto很不错,功能相同,但缺点是它们使连接更加模糊(尤其是Eventbus)。如果你已经使用rx,我认为最好还是继续使用它
这是一篇关于这个话题的独创性文章
本地广播
实现这一点的经典方法是使用,但在我的AOP中,它们是一个难题我会使用基于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);
}
}
发送消息:
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));
为什么不使用一个接口呢?如果你真的喜欢使用意图,那么在片段中注册一个BroadcastReceiver应该是你的解决方案,也许看看,这似乎是相关的:这种方法是如此的内存泄漏。它与runOnUiThread无关。您对本质上不稳定的资源有一个强大的静态引用。这样可以防止GC
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));