Android DataBinding中调用Kotlin函数类型实现重试回调问题
基于BaseObservable的Android DataBinding网络状态ViewModel实现(含重试回调)
看起来你已经有了一个不错的开头,我来帮你完善这个实现,确保能在按钮点击时正确触发重试回调,同时把网络状态的UI绑定逻辑补全。
首先,我们先定义NetworkState密封类,明确网络请求的几种核心状态:
sealed class NetworkState { object Loading : NetworkState() data class Error(val message: String) : NetworkState() object Success : NetworkState() }
接下来补全你的NetworkStateViewModel,添加错误信息绑定属性,以及触发重试回调的方法:
class NetworkStateViewModel(val retryCallback: () -> Unit) : BaseObservable() { var networkState: NetworkState? = null set(value) { field = value notifyChange() // 状态变化时通知DataBinding更新所有绑定属性 } @Bindable val isLoading: Boolean get() = networkState is NetworkState.Loading @Bindable val isShowingError: Boolean get() = networkState is NetworkState.Error @Bindable val errorMessage: String? get() = (networkState as? NetworkState.Error)?.message // 供布局按钮点击调用的重试方法,内部触发传入的回调 fun retry() { retryCallback.invoke() } }
关键部分说明:
notifyChange():当networkState更新时,会通知DataBinding刷新所有带有@Bindable注解的属性,确保UI实时同步状态变化。retry()方法:这是暴露给布局的点击事件入口,内部直接调用构造函数传入的retryCallback,实现了重试逻辑与ViewModel的解耦,外部可以灵活传入具体的重试操作(比如重新发起网络请求)。
布局文件中的绑定示例:
现在你可以在XML布局中通过DataBinding绑定这些属性和点击事件:
<layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="viewModel" type="com.yourpackage.NetworkStateViewModel" /> </data> <!-- 加载中显示的进度条 --> <ProgressBar android:layout_width="wrap_content" android:layout_height="wrap_content" android:visibility="@{viewModel.isLoading ? View.VISIBLE : View.GONE}" /> <!-- 错误状态显示区域 --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:visibility="@{viewModel.isShowingError ? View.VISIBLE : View.GONE}"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{viewModel.errorMessage}" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="重试" android:onClick="@{() -> viewModel.retry()}" /> </LinearLayout> <!-- 成功状态下的内容区域 --> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="@{viewModel.networkState instanceof NetworkState.Success ? View.VISIBLE : View.GONE}"> <!-- 这里放置你的业务内容布局 --> </FrameLayout> </layout>
在Activity/Fragment中初始化ViewModel并绑定:
最后,在页面中完成ViewModel的初始化与DataBinding的关联:
class YourActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val binding = DataBindingUtil.setContentView<YourLayoutBinding>(this, R.layout.your_layout) // 传入具体的重试逻辑,比如重新发起网络请求 val networkViewModel = NetworkStateViewModel { fetchData() } binding.viewModel = networkViewModel binding.lifecycleOwner = this // 确保绑定能感知页面生命周期 } private fun fetchData() { // 这里写你的网络请求逻辑 } }
这样整个流程就完全打通了:当网络状态变为Error时,错误提示区域自动显示,点击重试按钮会触发你传入的retryCallback执行重试操作;状态变为Loading时显示进度条,Success时则展示业务内容区域。
内容的提问来源于stack exchange,提问作者AdamMc331
相关产品推荐
相关产品推荐

