【问题标题】:How to properly reload liveData manually in Android?如何在 Android 中手动正确重新加载 liveData?
【发布时间】:2019-04-27 07:31:30
【问题描述】:

我的应用是一个基本的新闻应用,它从 Guardian API 提供的 JSON 中获取数据。 我使用原始 Java 代码(不使用改造)解析了 JSON 中的值。

然后我在 NewsFeedViewModel 类中获取 LiveData,该类扩展为 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

【问题讨论】:

    标签: java android refresh viewmodel android-livedata


    【解决方案1】:

    你需要完全按照我在this Reddit post中所做的:

    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 final GithubRepository githubRepository;
    
        public YourViewModel(GithubRepository githubRepository, SavedStateHandle savedStateHandle) {
             this.githubRepository = githubRepository;
        }
    
        private final LiveData<String> userId = savedStateHandle.getLiveData("userId"); // from args
    
        private final RefreshLiveData<List<Project>> refreshLiveData = Transformations.switchMap(userId, (uId) -> {
            return githubRepository.getProjectList(uId);
        });
    
        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;
    }
    

    【讨论】:

      【解决方案2】:

      在 kotlin 风格中:

      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 viewModel: MyViewModel by viewModel()
      
          override fun onCreate(savedInstanceState: Bundle?) {
              super.onCreate(savedInstanceState)
      
              viewModel.goals.observe(this) { result ->
                  // update UI
              }
      
              // refresh
              viewModel.refresh()
          }
      }
      
      class MyViewModel(useCase: MyUseCase): ViewModel() {
      
          private val _goals = RefreshableLiveData {
              useCase.getGoals()
          }
      
          val goals: LiveData<Result<List<GoalItem>>>
              get() = _goals.map(GoalItem::fromEntity)
      
          fun refresh() {
              _goals.refresh()
          }
      }
      
      class MyUseCase {...}
      ...
      

      【讨论】:

        猜你喜欢
        • 2018-11-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多