我有observable的奇怪行为。我从ViewModel getData()中的SecondFragment void调用它应该逐秒发出值,但它不会。在日志中我只有:
getData called.
getData subscribe
当我返回到上一个片段(ViewModel和Fragment被销毁(一次性处置))并再次输入时,它会正常工作。此外,当我第二次从按钮调用此方法时。
有人知道为什么它不能正常工作吗?
BaseFragmentCompat
public abstract class PreferenceFragmentCompatBase extends PreferenceFragmentCompat {
private static final String TAG = "PreferenceFragmentCompa";
private final CompositeDisposable mCompositeDisposable = new CompositeDisposable();
public void addCompositeDisposable(Disposable disposable) {
mCompositeDisposable.add(disposable);
}
@Override
public void onDestroy() {
super.onDestroy();
mCompositeDisposable.dispose();
}
@Override
public void onDestroyView() {
super.onDestroyView();
mCompositeDisposable.clear();
}
public DisposableObserver<String> preferenceSubscriber(Preference preference) {
return new DisposableObserver<String>() {
@Override
public void onNext(@NonNull String s) {
if (preference == null)
return;
preference.setSummary(s);
}
@Override
public void onError(@io.reactivex.rxjava3.annotations.NonNull Throwable e) {
if (preference == null)
return;
preference.setSummary(NO_DATA);
}
@Override
public void onComplete() {
Log.d(TAG, "onComplete: onComplete");
}
@Override
protected void onStart() {
if (preference == null)
return;
preference.setSummary("Ładowanie...");
}
};
}
protected NavBackStackEntry navGraphViewModels(int navigation) {
return NavHostFragment.findNavController(this).getBackStackEntry(navigation);
}
}
第二片段
public class SecondFragment extends PreferenceFragmentCompatBase {
private static final String TAG = "SettingsDataiCzasFragme";
private SettingsDataiCzasViewModel mViewModel;
private NavController navController;
public SettingsDataiCzasFragment() {
}
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.settings_dataiczas);
mViewModel = new ViewModelProvider(navGraphViewModels(R.id.navigation_data_i_czas)).get(SettingsDataiCzasViewModel.class);
navController = NavHostFragment.findNavController(this);
observeData();
mViewModel.getData(); // here I called void in ViewModel but nothing happends
}
private void observeData() {
final Preference dateTime = findPreference(Constants.date_time_cash);
addCompositeDisposable(
mViewModel.getDateAndTime()
.doOnSubscribe(disposable -> Log.d(TAG, "observeData: subscribe."))
.doOnTerminate(() -> Log.d(TAG, "observeData: terminate"))
.doOnDispose(() -> Log.d(TAG, "observeData: disposed"))
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.map(zonedDateTimeStr -> FormatHelper.convertInstanttoSimpleDate(zonedDateTimeStr, true, true, true))
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(preferenceSubscriber(dateTime))
);
}
@Override
public boolean onPreferenceTreeClick(Preference preference) {
.....
}
基本视图模型
public abstract class SettingsAbstractViewModel extends AndroidViewModel {
private static final String TAG = "SettingsServerAbstractV";
public static final String NO_DATA = "Brak danych";
private final CompositeDisposable mCompositeDisposable;
public SettingsAbstractViewModel(@NonNull Application application) {
super(application);
mCompositeDisposable = new CompositeDisposable();
}
/**
* Funkcja pobierająca dane z różnych źródeł przy utworzeniu ViewModelu
*/
public abstract void getData();
public void addCompositeDisposable(Disposable disposable) {
mCompositeDisposable.add(disposable);
}
@Override
public void onCleared() {
super.onCleared();
Log.i(TAG, "onCleared: called for: " + this);
Log.i(TAG, "onCleared: disposable: " + mCompositeDisposable);
mCompositeDisposable.clear();
}
}
视图模型
public class VIEWMODEL extends SettingsAbstractViewModel {
private static final String TAG = "SettingsDataiCzasViewModel";
private TimeRepository mTimeRepository;
private int[] zoneOffsets;
private String[] zoneNames;
private BehaviorSubject<ZonedDateTime> dateAndTime;
public PublishSubjectDataRx3<ZonedDateTime> syncTimeResult;
private Disposable getTimeDisposable;
private Disposable subscribe;
public SettingsDataiCzasViewModel(@NonNull Application application) {
super(application);
mTimeRepository = new TimeRepository(getApplication());
dateAndTime = BehaviorSubject.create();
syncTimeResult = new PublishSubjectDataRx3<>();
}
@Override
public void getData() {
Log.d(TAG, "getData: called.");
if (subscribe != null)
subscribe.dispose();
subscribe = Observable.interval(0, 1000, TimeUnit.MILLISECONDS)
.subscribeOn(Schedulers.computation())
.doonSubscribe(ignore -> Log.d(TAG, "getData: subscribe))
.doonDispose(() -> Log.d(TAG, "getData: dispose))
.switchMapSingle(ignore ->
mTimeRepository.getZonedTime()
.subscribeOn(Schedulers.io())
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io()))
.subscribe(
zonedDateTimeStr -> {
dateAndTime.onNext(zonedDateTimeStr);
},
e -> Log.e(TAG, "getData: ", e)
);
}
@Override
public void onCleared() {
super.onCleared();
if (subscribe != null)
subscribe.dispose();
}
public void downloadTimeFromServer(int zoneOffset) {
Log.d(TAG, "downloadTimeFromServer: called.");
syncTimeResult.loading();
getTimeDisposable = mTimeRepository.getDateAndTimeFromServer()
.subscribeOn(Schedulers.io())
.doOnEvent((aLong, throwable) -> Log.d(TAG, "downloadTimeFromServer: " + aLong + throwable))
.flatMapCompletable(aLong -> mTimeRepository.setDateAndTimeFromUtc(aLong, zoneOffset))
.doOnEvent(throwable -> Log.d(TAG, "downloadTimeFromServer: " + throwable))
.andThen(Single.defer(() -> mTimeRepository.getZonedTime()))
.doOnEvent((zonedDateTime, throwable) -> Log.d(TAG, "downloadTimeFromServer: " + zonedDateTime.toString() + throwable))
.observeOn(Schedulers.io())
.subscribe(
zonedDateTime -> {
syncTimeResult.success(zonedDateTime);
},
e -> {
Logs.e(TAG, "getTimeFromServer: ", e);
String errorMsg;
if (e instanceof UnknownHostException)
errorMsg = "Wystąpił błąd podczas próby komunikacji z serwerem.\nSprawdź połączenie z internetem.";
else
errorMsg = e.getMessage();
syncTimeResult.error(errorMsg);
}
);
addCompositeDisposable(getTimeDisposable);
}
public Observable<Resource<ZonedDateTime>> getSyncTimeResult() {
return syncTimeResult.getOrigin();
}
public Observable<ZonedDateTime> getDateAndTime() {
return dateAndTime;
}
}