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

Android中如何结合Room与CoinGecko API在RecyclerView展示加密货币组合

加密货币组合展示与盈亏计算实现方案

1. 定义组合数据模型

先创建一个整合本地与API数据的实体类,把需要展示的字段都包含进去,同时预留盈亏计算结果的字段:

data class CryptoPortfolioItem(
    val id: String,
    val name: String,
    val symbol: String,
    val buyPrice: Double,
    val currentPrice: Double,
    val profitLoss: Double,
    val profitLossPercentage: Double
)

2. 合并本地数据与API价格

步骤拆解:

  • 从Room数据库取出所有持仓的加密货币记录
  • 收集所有加密货币ID,调用CoinGecko的批量价格接口(推荐用/simple/price?ids=xxx,xxx&vs_currencies=usd,减少请求次数)获取当前价格
  • 遍历本地数据,匹配对应ID的当前价格,计算盈亏:
    • 盈亏金额 = 当前价格 - 买入价
    • 盈亏百分比 = ((当前价格 - 买入价) / 买入价) * 100(注意处理买入价为0的异常情况)

核心代码示例:

// 从Room拉取本地持仓数据
val localCryptos = cryptoDao.getAllCryptos()
// 拼接ID列表用于批量请求
val cryptoIds = localCryptos.joinToString(",") { it.id }
// 调用API获取批量价格(假设已封装CoinGecko API请求类)
val priceMap = coinGeckoApi.getBatchPrices(cryptoIds, "usd")
// 合并数据并计算盈亏
val portfolioList = localCryptos.map { localItem ->
    val currentPrice = priceMap[localItem.id]?.get("usd") ?: 0.0
    val profitLoss = currentPrice - localItem.buyPrice
    val profitLossRate = if (localItem.buyPrice != 0.0) {
        (profitLoss / localItem.buyPrice) * 100
    } else 0.0

    CryptoPortfolioItem(
        id = localItem.id,
        name = localItem.name,
        symbol = localItem.symbol,
        buyPrice = localItem.buyPrice,
        currentPrice = currentPrice,
        profitLoss = profitLoss,
        profitLossPercentage = profitLossRate
    )
}

3. RecyclerView适配展示

创建对应的Adapter,把组合数据绑定到UI上,同时给盈亏设置不同颜色区分正负:

class CryptoPortfolioAdapter(private val portfolioList: List<CryptoPortfolioItem>) :
    RecyclerView.Adapter<CryptoPortfolioAdapter.ViewHolder>() {

    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val tvName: TextView = itemView.findViewById(R.id.tv_crypto_name)
        val tvSymbol: TextView = itemView.findViewById(R.id.tv_crypto_symbol)
        val tvCurrentPrice: TextView = itemView.findViewById(R.id.tv_current_price)
        val tvProfitLoss: TextView = itemView.findViewById(R.id.tv_profit_loss)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val itemView = LayoutInflater.from(parent.context)
            .inflate(R.layout.item_crypto_portfolio, parent, false)
        return ViewHolder(itemView)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val item = portfolioList[position]
        holder.tvName.text = item.name
        holder.tvSymbol.text = item.symbol.uppercase()
        holder.tvCurrentPrice.text = "$${String.format("%.2f", item.currentPrice)}"

        // 格式化盈亏文本,正负用不同颜色
        val (profitText, textColor) = if (item.profitLoss >= 0) {
            Pair(
                "+$${String.format("%.2f", item.profitLoss)} (${String.format("%.2f", item.profitLossPercentage)}%)",
                holder.itemView.context.getColor(R.color.green_positive)
            )
        } else {
            Pair(
                "-$${String.format("%.2f", -item.profitLoss)} (${String.format("%.2f", -item.profitLossPercentage)}%)",
                holder.itemView.context.getColor(R.color.red_negative)
            )
        }
        holder.tvProfitLoss.text = profitText
        holder.tvProfitLoss.setTextColor(textColor)
    }

    override fun getItemCount() = portfolioList.size
}

4. 数据更新与生命周期管理

  • 把数据获取逻辑放到ViewModel中,用LiveData或者Flow暴露处理好的组合数据,在Activity/Fragment中观察数据变化,刷新RecyclerView
  • 处理API请求异常:比如网络不通时,显示本地缓存的价格或者提示用户检查网络
  • 可以添加下拉刷新功能,触发重新拉取价格并更新列表

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 04:33:37