You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:51:19