#java #android #kotlin #android-livedata
#java #Android #kotlin #android-livedata
Вопрос:
В Kotlin есть метод расширения observeOnce (https://code.luasoftware.com/tutorials/android/android-livedata-observe-once-only-kotlin /) это поведение, которое я хочу воспроизвести в Java. Насколько я понял из поиска в Google, вы не можете использовать методы расширения Kotlin в java (возможно, это неправильно), поэтому у меня есть два варианта использования SingleEventLiveData, которые я реализовал и которые мне не нравятся, и удаление моего observer после использования;
final LiveData<List<String>> stringsLiveData = mViewModel.getStrings();
stringsliveData.observe(getViewLifecycleOwner(), strings -> {
// Do stuff with data here
stringsLiveData.removeObservers(getViewLifecycleOwner());
});
Существует ли эквивалентный метод, который можно использовать в качестве ссылки выше, чтобы;
mViewModel.getStrings().observeOnce(getViewLifecycleOwner(), strings -> {
//Do stuff here
});
Редактировать: Согласно принятому ответу ниже (изменено для компиляции) У меня есть;
class LiveDataUtils {
public static <T> void observeOnce(LiveData<T> liveData, Observer<T> observer) {
liveData.observeForever(o -> {
liveData.removeObserver(observer);
observer.onChanged(o);
});
}
}
и простое использование этого;
LiveDataUtils.observeOnce(
mViewModel.getStrings(),
strings -> {
// Do some work here
}
);
Комментарии:
1. Вы можете использовать методы расширения из Java. Это просто статические методы с первым параметром, являющимся получателем. Я не уверен, ограничили ли они это как-то в случае с данными в реальном времени, но, возможно, стоит попробовать
2. Да, я поиграл с этим, но, к сожалению, не могу заставить что-либо работать так, как я хочу.
3. Вы не должны удалять ВСЕХ наблюдателей, вы должны удалить только тот,
observer
который вы указали методом.4. @EpicPandaForce обновлено, чтобы удалить только отдельного наблюдателя, что вы думаете о observe (владелец, o) против observeForever (o)
5. Что это зависит от того, что вы делаете. Хотя предполагаемый способ выполнения действий заключается в том, чтобы получать события только после
onStart
и доonStop
. Я использовал observeForever внутри ViewModel, но я должен был использовать Transformations.switchMap (который внутренне использует observeForever / removeObserver).
Ответ №1:
Каждая функция расширения Kotlin решается статически, что означает, что вы можете сделать то же самое в Java с помощью статических функций. Это не так читаемо или интуитивно понятно, как функции расширения, но выполняет ту же работу.
Создайте класс util со статическим методом:
public class LiveDataUtils {
public static <T> void observeOnce(LiveData<T> liveData, Observer<T> observer) {
liveData.observeForever(new Observer<T>() {
@Override
public void onChanged(T t) {
liveData.removeObserver(this);
observer.onChanged(t);
}
});
}
}
Я не тестировал код, поэтому в нем могут быть некоторые ошибки. Смысл был в том, чтобы показать вам, как вы можете заменить функции расширения в Java.
РЕДАКТИРОВАТЬ: Обновлено в соответствии с последующими действиями @Marek Potkan, поскольку это принятый ответ. Как я уже упоминал, я не тестировал код и по ошибке предоставил неверную ссылку.
Комментарии:
1. Я бы рекомендовал переместить removeObserver выше
observer.onChange
, так как вы могли бы получить другой элемент через LiveData, прежде чем удалять его.2. Я немного изменил этот код, чтобы он мог компилироваться, и он работает просто отлично, спасибо! Я отредактирую свой ответ, чтобы показать правильный код.
3. @Ge3ng имеет правильную точку зрения, вы можете переключиться, чтобы избежать получения нескольких элементов. Рад, что смог помочь, всегда пожалуйста 🙂
Ответ №2:
ответ @deluxe1 не сработал бы. observer
Вызывается observer
удаление, но это не тот, который используется в observeForever
методе. Вместо лямбда-функции здесь следует использовать расширенную версию:
public static <T> void observeOnce(LiveData<T> liveData, Observer<T> observer) {
liveData.observeForever(new Observer<T>() {
@Override
public void onChanged(T t) {
liveData.removeObserver(this);
observer.onChanged(t);
}
});
}
Я протестировал оба подхода.