Android-PullToRefresh与ViewModel结合:配置变更时的状态保存

Android-PullToRefresh与ViewModel结合:配置变更时的状态保存

【免费下载链接】Android-PullToRefresh DEPRECATED 【免费下载链接】Android-PullToRefresh 项目地址: https://gitcode.com/gh_mirrors/an/Android-PullToRefresh

痛点解析:旋转屏幕后刷新状态丢失的问题

用户在使用下拉刷新控件时,常遇到设备旋转或配置变更后刷新状态丢失的问题。传统实现中,刷新状态存储在Activity或Fragment中,配置变更会导致这些组件重建,从而丢失状态数据。以PullToRefreshListActivity.java为例,其通过AsyncTask处理刷新逻辑,但未处理配置变更场景,导致旋转屏幕后刷新状态无法恢复。

ViewModel解决方案:分离数据与UI控制器

ViewModel组件旨在存储和管理与UI相关的数据,且在配置变更时保持数据持久性。结合Android-PullToRefresh实现状态保存需以下步骤:

1. 添加依赖

build.gradle中添加ViewModel依赖:

implementation "androidx.lifecycle:lifecycle-viewmodel:2.5.1"
implementation "androidx.lifecycle:lifecycle-livedata:2.5.1"

2. 创建刷新状态ViewModel

定义RefreshStateViewModel保存刷新状态和数据:

public class RefreshStateViewModel extends ViewModel {
    private MutableLiveData<Boolean> isRefreshing = new MutableLiveData<>(false);
    private MutableLiveData<List<String>> listData = new MutableLiveData<>(new ArrayList<>());

    public LiveData<Boolean> getIsRefreshing() {
        return isRefreshing;
    }

    public LiveData<List<String>> getListData() {
        return listData;
    }

    public void setIsRefreshing(boolean refreshing) {
        isRefreshing.setValue(refreshing);
    }

    public void setListData(List<String> data) {
        listData.setValue(data);
    }
}

3. 重构Activity实现状态保存

修改PullToRefreshListActivity.java,使用ViewModel保存状态:

public class PullToRefreshListActivity extends AppCompatActivity {
    private PullToRefreshListView mPullRefreshListView;
    private RefreshStateViewModel viewModel;
    private ArrayAdapter<String> mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_ptr_list);
        
        // 初始化ViewModel
        viewModel = new ViewModelProvider(this).get(RefreshStateViewModel.class);
        
        mPullRefreshListView = findViewById(R.id.pull_refresh_list);
        mAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, new ArrayList<>());
        mPullRefreshListView.setAdapter(mAdapter);

        // 观察刷新状态变化
        viewModel.getIsRefreshing().observe(this, isRefreshing -> {
            if (isRefreshing) {
                mPullRefreshListView.setRefreshing(true);
            } else {
                mPullRefreshListView.onRefreshComplete();
            }
        });

        // 观察列表数据变化
        viewModel.getListData().observe(this, data -> {
            mAdapter.clear();
            mAdapter.addAll(data);
            mAdapter.notifyDataSetChanged();
        });

        // 设置刷新监听器
        mPullRefreshListView.setOnRefreshListener(refreshView -> {
            new GetDataTask().execute();
        });

        // 恢复状态(如旋转后)
        if (viewModel.getIsRefreshing().getValue()) {
            mPullRefreshListView.setRefreshing(true);
        }
    }

    private class GetDataTask extends AsyncTask<Void, Void, List<String>> {
        @Override
        protected void onPreExecute() {
            viewModel.setIsRefreshing(true);
        }

        @Override
        protected List<String> doInBackground(Void... params) {
            // 模拟网络请求
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {}
            return Arrays.asList("新数据1", "新数据2", "新数据3");
        }

        @Override
        protected void onPostExecute(List<String> result) {
            viewModel.setListData(result);
            viewModel.setIsRefreshing(false);
        }
    }
}

4. 实现原理说明

  • 状态保存:通过ViewModel的isRefreshinglistData字段保存刷新状态和列表数据,配置变更时ViewModel实例保留
  • 数据恢复:Activity重建时通过ViewModelProvider获取原ViewModel实例,恢复状态并更新UI
  • 生命周期感知:使用LiveData实现数据观察,确保UI组件在活跃状态下接收数据更新

关键代码解析

PullToRefreshBase状态管理

PullToRefreshBase.java中提供了状态保存机制:

@Override
protected final void onSaveInstanceState(Parcelable state) {
    Bundle bundle = new Bundle();
    bundle.putInt(STATE_STATE, mState.getIntValue());
    bundle.putInt(STATE_MODE, mMode.getIntValue());
    // 保存其他状态...
    super.onSaveInstanceState(bundle);
}

但该方法仅保存视图状态,ViewModel方案可实现跨配置变更的数据持久化。

ViewModel与PullToRefresh结合优势

  1. 数据与UI分离:ViewModel独立于UI控制器,避免数据存储在Activity/Fragment中
  2. 自动状态恢复:配置变更后无需手动保存/恢复数据
  3. 生命周期安全:LiveData确保仅在UI活跃时更新,避免内存泄漏

完整实现流程图

mermaid

注意事项

  1. ViewModel不应持有Activity上下文引用,避免内存泄漏
  2. 复杂数据操作应使用ViewModelScope协程或AsyncTask
  3. 配合Room数据库可实现持久化存储,适应进程重启场景

通过ViewModel与Android-PullToRefresh的结合,可彻底解决配置变更导致的状态丢失问题,提升应用稳定性和用户体验。完整实现可参考sample模块中的示例代码结构。

【免费下载链接】Android-PullToRefresh DEPRECATED 【免费下载链接】Android-PullToRefresh 项目地址: https://gitcode.com/gh_mirrors/an/Android-PullToRefresh

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值