首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >RxJava安卓换向及网络请求

RxJava安卓换向及网络请求
EN

Stack Overflow用户
提问于 2018-07-04 16:27:56
回答 2查看 1.1K关注 0票数 0

我是RxJava的新手,我需要将它集成到现有的项目中。我需要重构现有代码,为网络添加Observables (套接字IO)。

目前,当发出网络请求(客户端->服务器)时,会向HashMap添加一个回调(接口),一旦请求完成,它会将数据传递回调用者:

代码语言:javascript
复制
// Singleton
public class API {

   public void checkTicket(String ticketId, final String networkRequestId, Callback callback) {
      // Add the callback to the hashmap
      registerCallback(networkRequestId, callback);

      JSONObject json = RequestFactory.createTicketCheckerRequest(ticketId);

      // Make the network request
      getSocket().checkTicket(json, new Callback() {
          @Override
          public void onRequestDone(Response response) {

              // Retrieve the callback
              callback = getCallback(networkRequestId);

              // Don't keep reference, remove from hashmap
              unsubscribeCallback(networkRequestId);

              // Check if it's unsuccessful and build the corresponding error response
              if (!response.isSuccess()) {
                  // build custom error response
                  response = ResponseFactory.buildError(response);
              }

              // Deliver response from server
              callback.onRequestDone(response);
          }
      });
  }

}

可以从ActivitiesFragments调用它

代码语言:javascript
复制
private void checkTicket() {
   String ticketId = editText.getText().toString();

   API.getInstance().checkTicket(ticketId, REQUEST_ID_CHECK_TICKET, new Callback() {
      @Override
      protected void onRequestDone(Response response) {
         textView.setText(response.getData());
      }
   });
}

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

   // Removes callback from HashMap in case of the UI is destroyed before the arrives
   API.getInstance().unsubscribe(REQUEST_ID_CHECK_TICKET);
}

上面的代码可以工作,但它与UI的生命周期非常紧密,有时会导致内存泄漏,因为onDestroy()不会被调用(如果你在活动之间导航,安卓操作系统会从堆栈中删除“暂停的”活动),或者因为匿名内部类(回调)持有对UI的引用,并且从现在开始我需要支持方向更改

这是我使用RxJava实现的代码

接口

代码语言:javascript
复制
public Observable<Response> checkTicket(String ticketId) {
   return Observable.create(subscriber -> {
      JSONObject json = RequestFactory.createTicketCheckerRequest(ticketId);

      // Make the network request
      getSocket().checkTicket(json, new Callback() {
         @Override
         public void onRequestDone(Response response) {
            subscriber.onNext(response);
            subscriber.onComplete();
         }
      });
   });
}

下面是从UI中调用它的方式:

代码语言:javascript
复制
private CompositeDisposable mDisposables = new CompositeDisposable();

private void checkTicket() {
   //////

   Disposable disposable = API.getInstance().checkTicket(ticketId)
      .observeOn(AndroidSchedulers.mainThread())
      .subscribeOn(Schedulers.io())
      .subscribe(result -> {
         textView.setText(result.getData());
      });

   mDisposables.add(disposable);
}

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

   if (!mDisposables.isDisposed()) {
      mDisposables.dispose();
   }
}

上面的RxJava正在工作,但是,如果方向发生更改,则不会返回数据,因为Observer已取消订阅。

  1. 上面的实现是否正确?
  2. 如果不执行请求该如何订阅?订阅并等待数据更改。

另一种选择是EventBus,但这只是B计划。EventBus完全符合我的要求,订阅并等待数据更改,但我想驱逐样板。

我读过其他使用FragmentsetRetainInstance(true)的文章,但是如果我需要在Activity中使用它呢?如果我不想保留Fragment的状态呢?人们建议使用MVVMMVP架构,但我没有时间重构整个项目。

EN

回答 2

Stack Overflow用户

发布于 2018-07-05 01:05:55

我建议您迁移到MVVM。使用您提供的代码,这并不难。下面是一个样例代码,展示了它的外观

Your ModelView

代码语言:javascript
复制
public class MyViewModel extends ViewModel {
    private CompositeDisposable mDisposables = new CompositeDisposable();
    private MutableLiveData<Response> response;

    public LiveData<Response> getResponse() {
        if (response == null) {
            response = new MutableLiveData<Response>();
            loadData();
        }
        return response;
    }

    private void loadData() {
        Disposable disposable = API.getInstance().checkTicket(ticketId)
          .observeOn(AndroidSchedulers.mainThread())
          .subscribeOn(Schedulers.io())
          .subscribe(result -> {
             response.postValue(result.getData());
          });

       mDisposables.add(disposable);
    }

    void onCleared()
    {
        super.onCleared();
        mDisposables.clear(); //no more leaks. It takes care of lifecycle for you
    }
}

Your Activity

代码语言:javascript
复制
public class MyActivity extends AppCompatActivity {
    public void onCreate(Bundle savedInstanceState) {

        MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
        model.getResponse().observe(this, response -> {
            // update UI
            textView.setText(response); //response = Response object from Live data
        });
    }
}
票数 3
EN

Stack Overflow用户

发布于 2018-07-04 18:11:01

如果您不想处理配置更改,而希望缓存来自可观察对象的数据,则可以使用BehaviorSubjects和一个热可观察对象。这将允许您获取observable发布的最新项。

除此之外,我建议您使用架构组件中的ViewModel。它将允许您创建绑定到活动但不受生命周期影响的组件(显然,终止除外)。令人惊讶的是,使用setRetainInstance(true)将ViewModelProviders实现为片段。你不必完全重构整个应用程序。只需移动您想要在配置更改期间保留的那些。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51169122

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档