如何在 Android 中手动正确重新加载 liveData?

Sye*_*han 5 java android refresh viewmodel android-livedata

我的应用程序是一个基本的新闻应用程序,它从 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

YMo*_*ier 5

在科特林风格中:

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

例子:

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 {...}
...
Run Code Online (Sandbox Code Playgroud)


Epi*_*rce 2

您需要完全按照我在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);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以做

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后存储库可以执行以下操作:

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;
}
Run Code Online (Sandbox Code Playgroud)