Как использовать наблюдателей с обратными вызовами сокетов?

#java #android #observable #rx-java2

#java #Android #наблюдаемый #rx-java2

Вопрос:

Я разработчик Android, который заинтересован в тестировании новых технологий. Знаете, я хочу использовать компоненты архитектуры для улучшения своих проектов.

Я хочу перечислить статьи с сервера и показать их в RecyclerView. Следует отметить, что я использовал WebSocket для связи с сервером.

Моя процедура заключается в следующем:

Сначала я вызвал метод loadArticles из класса ViewModel:

 BlogViewModel = ViewModelProvders.of(this).get(BlogViewModel.class);
viewModel.loadArticles();
  

Ниже тела BlogViewModel:

 public class BlogViewModel extends ViewModel {

private BlogRepository repository;
private CompositeDisposable compositeDisposable = new CompositeDisposable();

public ObservableField<Boolean> isLoading = new ObservableField<>();
public MutableLiveData<List<Article>> articles = new MutableLiveData<>();


public BlogViewModel() {
    this.repository = new BlogRepository();
}

public void loadArticles() {
    isLoading.set(true);

    compositeDisposable.add(repository
            .getArticles()
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeWith(new DisposableObserver<List<Article>>() {
                @Override
                public void onNext(List<Article> data) {
                    articles.setValue(data);
                }

                @Override
                public void onError(Throwable e) {
                    // FIXME: 3/31/2019
                }

                @Override
                public void onComplete() {
                    isLoading.set(false);
                }
            }));
}

@Override
protected void onCleared() {
    super.onCleared();

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

Кроме того, класс BlogRepository определяется следующим образом:

 public class BlogRepository {

private BlogRemoteDataSource remoteDataSource = BlogRemoteDataSource.getInstance();

public Observable<List<Article>> getArticles() {
    if (Util.isConnect()) {
        return remoteDataSource.getArticles();
    } else {
        return null;
    }
  }
}
  

И класс BlogRemoteDataSource определяется следующим образом:

 public class BlogRemoteDataSource {

private Application app = (Application) Application.getInstance();
private List<Article> articles;

public static BlogRemoteDataSource getInstance() {
    return new BlogRemoteDataSource();
}

public Observable<List<Article>> getArticles() {
    JSONObject objData = new JSONObject();
    try {
        objData.put("itemID", "");
    } catch (JSONException e) {
        e.printStackTrace();
    }

    app.getSocket().observe(app.getOwner(), socket -> socket.event(Api.EVENT_GET_ARTICLE)
            .data(objData)
            .setCallbacks(new SocketCallback() {
                @Override
                public void onSuccess(JSONObject data) {
                    try {
                        articles = Article.parse(data.getJSONArray(Constant.PARAM_BODY));
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void onError(int code, String message) {
                }
            }).send());

    return Observable.just(articles);
    }
}
  

Моя проблема заключается в том, что я возвращаю Observable.just (статьи) в качестве выходных данных. После выполнения этой строки метод onNext в классе BlogViewModel однажды запускается, но когда список статей берется с сервера и значение, метод onNext не запускается.

Пожалуйста, подскажите мне, как сообщить ViewModel, что данные готовы?

Заранее спасибо.

Комментарии:

1. Спасибо Тамир Абутбул!

Ответ №1:

Привет, вы можете использовать observeForever вместо observate только потому, что observeForever () не привязан ни к какому LifecycleOwner. поэтому используйте это, как показано ниже:

Сначала удалите свой класс BlogRepository и обновите BlogViewModel, как показано ниже:

 public class BlogViewModel extends ViewModel {

private CompositeDisposable compositeDisposable = new CompositeDisposable();
private BlogRemoteDataSource remoteDataSource = BlogRemoteDataSource.getInstance();
public ObservableField<Boolean> isLoading = new ObservableField<>();

public BlogViewModel() {
    this.repository = new BlogRepository();
}

public void loadArticles() {
    isLoading.set(true);
    remoteDataSource.getArticles();
}

@Override
protected void onCleared() {
    super.onCleared();
    if (!compositeDisposable.isDisposed()) {
        compositeDisposable.dispose();
    }
  }
}
  

Затем обновите BlogRemoteDataSource, как показано ниже:

 public class BlogRemoteDataSource {

private Application app = (Application) Application.getInstance();
public MutableLiveData<List<Article>> articles = new MutableLiveData<>();

public static BlogRemoteDataSource getInstance() {
    return new BlogRemoteDataSource();
}

public void getArticles() {
    JSONObject objData = new JSONObject();
    try {
        objData.put("itemID", "");
    } catch (JSONException e) {
        e.printStackTrace();
    }

    app.getSocket().observeForever(app.getOwner(), socket -> socket.event(Api.EVENT_GET_ARTICLE)
            .data(objData)
            .setCallbacks(new SocketCallback() {
                @Override
                public void onSuccess(JSONObject data) {
                    try {
                        List<Article> newArticeList = Article.parse(data.getJSONArray(Constant.PARAM_BODY));
                        articles.postValue(newArticeList);
                        articles.notifyObserver();
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void onError(int code, String message) {
                }
            }).send());
    }
}
  

Надеюсь, теперь это поможет !! 🙂

Комментарии:

1. Спасибо, мой друг, ваше решение исключило меня из LifecycleOwner, но оно по-прежнему не работает.