Как правильно перезагрузить liveData вручную в Android?
Мое приложение - это основное новостное приложение, которое извлекает данные из JSON, предоставляемые Guardian API. Я проанализировал значения из JSON, используя сырой код Java (без использования модификации).
Затем я получаю LiveData в классе NewsFeedViewModel, который расширяется как AndroidViewModel.
А затем во фрагменте я отправляю список адаптеру.
Вот проблемы, с которыми я сталкиваюсь: 1) сначала, если для выставляемых статей установлено значение 10, затем, если я перехожу к настройкам и меняю его на 2, то последние 8 статей исчезают, но пробел / пробел не собирается. Я все еще могу прокрутить пустой пробел. 2) если я постоянно изменяю количество статей, приложение перестает прокручиваться.
И у меня есть еще несколько сомнений, как обновить данные вручную, когда происходит swipeToRefresh?
Это ссылка на мой проект github: https://github.com/sdzshn3/News24-7-RV
Пример видео о проблеме, возникающей в приложении: https://drive.google.com/file/d/1gr_fabS2rqREuyecvGSG3IQ_jXOowlW7/view?usp=drivesdk
0 ответов
В стиле котлин:
class RefreshableLiveData<T>(
private val source: () -> LiveData<T>
) : MediatorLiveData<T>() {
private var liveData = source()
init {
this.addSource(liveData, ::observer)
}
private fun observer(data: T) {
value = data
}
fun refresh() {
this.removeSource(liveData)
liveData = source()
this.addSource(liveData, ::observer)
}
}
Пример:
class MainActivity : AppCompatActivity() {
private val useCase = TestUseCase(DataSource())
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
useCase.goals.observe(this) {
// update UI
}
// refresh
useCase.refresh()
}
}
class TestUseCase(dataSource: DataSource) : CommonUseCase() {
private val _goals = RefreshableLiveData {
callService { dataSource.loadData() }
}
val goals: LiveData<Resource<Boolean>> = _goals
fun refresh() {
_goals.refresh()
}
}
class DataSource {
fun loadData() = Resource.Success(true)
}
Вы должны сделать именно то, что я сделал в этом посте Reddit:
public class RefreshLiveData<T> extends MutableLiveData<T> {
public interface RefreshAction<T> {
private interface Callback<T> {
void onDataLoaded(T t);
}
void loadData(Callback<T> callback);
}
private final RefreshAction<T> refreshAction;
private final Callback<T> callback = new RefreshAction.Callback<T>() {
@Override
public void onDataLoaded(T t) {
postValue(t);
}
};
public RefreshLiveData(RefreshAction<T> refreshAction) {
this.refreshAction = refreshAction;
}
public final void refresh() {
refreshAction.loadData(callback);
}
}
Тогда вы можете сделать
public class YourViewModel extends ViewModel {
private RefreshLiveData<List<Project>> refreshLiveData; // TODO: make `final`
private final GithubRepository githubRepository;
public YourViewModel(GithubRepository githubRepository) {
this.githubRepository = githubRepository;
}
public void start(String userId) {
refreshLiveData = githubRepository.getProjectList(userId); // TODO: use Transformations.switchMap
}
public void refreshData() {
refreshLiveData.refresh();
}
public LiveData<List<Project>> getProjects() {
return refreshLiveData;
}
}
И тогда репозиторий может сделать:
public RefreshLiveData<List<Project>> getProjectList(String userId) {
final RefreshLiveData<List<Project>> liveData = new RefreshLiveData<>((callback) -> {
githubService.getProjectList(userId).enqueue(new Callback<List<Project>>() {
@Override
public void onResponse(Call<List<Project>> call, Response<List<Project>> response) {
callback.onDataLoaded(response.body());
}
@Override
public void onFailure(Call<List<Project>> call, Throwable t) {
}
});
});
return liveData;
}
Вы можете сделать это так
в своемViewModel
public class NewsViewModel extends AndroidViewModel {
private NewsRepository newsRepository;
private MutableLiveData<List<News>> news;
public NewsViewModel() {
super(application);
newsRepository = new NewsRepository(application);
news = newsRepository.getMutableLiveData();
}
public MutableLiveData<List<News>> getAllNews() {
return news;
}
public void Refresh() {
newsRepository = new NewsRepository(application);
news = newsRepository.getMutableLiveData();
}
}
Тогда в вашем Activity
swipeRefreshLayout.setOnRefreshListener(() -> {
viewModel.Refresh();
viewModel.getNewsData().observe(this, news -> mAdapter.setNews(news));
swipeRefreshLayout.setRefreshing(false);
});