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

Android开发:用Observable自动刷新Coingecko API币价数据

基于Kotlin Observable的币种价格自动刷新方案

要实现无需Handler的周期性+数据变化触发刷新,你可以结合Kotlin属性委托Delegates.observable(监听价格变量变更)和协程定时任务(周期性请求API)来完成,以下是具体实现步骤:

1. 定义可观察的价格变量

用Delegates.observable包装currentPrice,变量值变更时自动触发回调,在这里处理UI更新逻辑:

import kotlin.properties.Delegates
import androidx.lifecycle.ViewModel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.LiveData

class CoinDetailViewModel : ViewModel() {
    // 可观察的当前价格,初始值设为0.0
    var currentPrice: Double by Delegates.observable(0.0) { _, oldVal, newVal ->
        // 仅当值真正变化时通知UI
        if (oldVal != newVal) {
            _priceLiveData.postValue(newVal)
        }
    }

    // 用LiveData桥接UI与数据(MVVM架构下推荐)
    private val _priceLiveData = MutableLiveData<Double>()
    val priceLiveData: LiveData<Double> = _priceLiveData
}

2. 协程实现周期性API请求

利用ViewModel的viewModelScope(自动绑定生命周期,避免内存泄漏)启动定时任务,每隔5-10秒请求Coingecko API并更新currentPrice:

import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

class CoinDetailViewModel : ViewModel() {
    // ...上述变量定义...

    // 启动价格刷新任务,传入币种ID
    fun startPriceRefresh(coinId: String) {
        viewModelScope.launch {
            // 每8秒刷新一次(可在5000-10000毫秒间调整)
            while (true) {
                fetchCoinPrice(coinId)?.let { newPrice ->
                    currentPrice = newPrice
                }
                delay(8000)
            }
        }
    }

    // 调用Coingecko API获取价格的实际逻辑
    private suspend fun fetchCoinPrice(coinId: String): Double? {
        // 这里替换为你的API请求实现,比如用Retrofit
        return try {
            // 示例:假设API返回包含美元价格的响应
            val apiResponse = coingeckoApi.getCoinDetails(coinId)
            apiResponse.marketData.currentPrice.usd
        } catch (e: Exception) {
            e.printStackTrace()
            null
        }
    }
}

3. 页面中绑定UI更新

在Activity/Fragment中监听priceLiveData,并启动刷新任务:

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.observe

class CoinDetailActivity : AppCompatActivity() {
    private lateinit var viewModel: CoinDetailViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_coin_detail)

        viewModel = ViewModelProvider(this)[CoinDetailViewModel::class.java]

        // 监听价格变化,更新UI控件
        viewModel.priceLiveData.observe(this) { price ->
            tv_current_price.text = "$${String.format("%.2f", price)}"
        }

        // 从Intent获取币种ID(根据你的页面传参逻辑调整)
        val coinId = intent.getStringExtra("COIN_ID") ?: ""
        // 启动定时刷新
        viewModel.startPriceRefresh(coinId)
    }
}

额外优化建议

  • 如果在Activity/Fragment中直接启动协程,推荐用lifecycleScope.repeatOnLifecycle确保仅在页面处于活跃状态时执行任务:
    lifecycleScope.launch {
        repeatOnLifecycle(Lifecycle.State.STARTED) {
            while (true) {
                // 执行API请求和价格更新
                delay(8000)
            }
        }
    }
    
  • 已在Delegates.observable回调中通过oldVal != newVal实现防抖,避免API返回相同价格时重复更新UI。

内容的提问来源于stack exchange,提问作者hgokumus35

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 13:30:32