Я новичок в RxJava
, и мне нужно интегрировать его в существующий проект. Мне нужно провести рефакторинг существующего кода, добавив Observables
для работы в сети (Socket IO).
В настоящее время, когда выполняется сетевой запрос (клиент -> сервер), к HashMap
добавляется обратный вызов (интерфейс), и после завершения запроса он доставляет данные обратно вызывающей стороне:
// 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);
}
});
}
}
Может вызываться с Activities
и Fragments
:
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);
}
Приведенный выше код работает, но он действительно тесно связан с жизненным циклом пользовательского интерфейса и иногда вызывает утечку памяти, поскольку onDestroy()
не вызывается (если вы переходите между действиями, а ОС Android убивает «приостановленные» действия из стека) или потому что анонимные внутренние классы (обратные вызовы), которые содержат ссылку на пользовательский интерфейс, и отныне мне нужно поддерживать изменение ориентации .
Это код, который я реализовал, используя RxJava
:
API
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();
}
});
});
}
Вот как он вызывается из интерфейса:
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
отписано.
- Корректна ли вышеприведенная реализация?
- Как мне подписаться, не выполняя запрос? Подпишитесь и ждите изменения данных.
Другой альтернативой будет EventBus , но это всего лишь план B. EventBus точно соответствует моим требованиям, подписывайтесь и ждите изменения данных, но я хочу исключить шаблон.
Я читал другие статьи, используя Fragment
setRetainInstance(true)
, но что, если мне нужно использовать его с Activity
? Что если я не хочу сохранять состояние Fragment
?
Люди предлагали использовать архитектуру MVVM
или MVP
, но у меня нет времени на рефакторинг всего проекта.