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

Android使用RecyclerView+DataBinding+ViewModel展示HTTP请求结果方案咨询

实现方案优化建议

1 上下文获取问题解决

首先明确:使用AndroidViewModel获取Application上下文初始化Volley是完全合规的实现,它持有的是全局Application上下文,不会引发内存泄漏。
如果希望进一步解耦ViewModel和Context,更符合关注点分离的架构原则,推荐将网络请求逻辑下沉到Repository层,全局初始化Volley单例:

// Volley全局单例实现
object VolleySingleton {
    @Volatile
    private var INSTANCE: RequestQueue? = null
    fun getInstance(context: Context): RequestQueue {
        return INSTANCE ?: synchronized(this) {
            val queue = Volley.newRequestQueue(context.applicationContext)
            INSTANCE = queue
            queue
        }
    }
}

如果选择直接用AndroidViewModel,参考实现如下:

class DevicesViewModel(application: Application) : AndroidViewModel(application) {
    private val requestQueue = Volley.newRequestQueue(application.applicationContext)
    // 其余原有逻辑保持不变
}

2 RecyclerView Adapter性能优化

当前每次数据更新都重新创建Adapter的实现性能较差,推荐使用ListAdapter配合DiffUtil实现局部刷新,无需每次重绘整个列表:

class NewDevicesAdapter : ListAdapter<Device, NewDevicesAdapter.ViewHolder>(DeviceDiffCallback) {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
        ViewHolder(
            AdapterNewDevicesBinding.inflate(LayoutInflater.from(parent.context))
        )

    override fun onBindViewHolder(holder: ViewHolder, position: Int) = holder.bind(getItem(position))

    inner class ViewHolder(val binding: AdapterNewDevicesBinding) : RecyclerView.ViewHolder(binding.root) {
        fun bind(item: Device) {
            binding.device = item
        }
    }

    companion object {
        private val DeviceDiffCallback = object : DiffUtil.ItemCallback<Device>() {
            override fun areItemsTheSame(oldItem: Device, newItem: Device): Boolean {
                // 用IP作为设备唯一标识,可根据实际业务调整
                return oldItem.ipAddress == newItem.ipAddress
            }

            override fun areContentsTheSame(oldItem: Device, newItem: Device): Boolean {
                return oldItem == newItem
            }
        }
    }
}

3 Fragment逻辑优化

避免重复创建Adapter,初始化一次后仅更新数据即可:

class NewDeviceFragment : Fragment() {
    private lateinit var binding: FragmentNewDeviceBinding
    private lateinit var adapter: NewDevicesAdapter

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        binding = FragmentNewDeviceBinding.inflate(layoutInflater).apply {
            devicesViewModel = ViewModelProvider(this@NewDeviceFragment).get(DevicesViewModel::class.java)
            lifecycleOwner = viewLifecycleOwner
            // 仅初始化一次Adapter
            adapter = NewDevicesAdapter()
            newDeviceRecyclerViewDevices.adapter = adapter
        }

        binding.devicesViewModel!!.items.observe(viewLifecycleOwner) { response ->
            // 直接提交新数据,DiffUtil自动计算差异局部刷新
            adapter.submitList(response)
        }

        return binding.root
    }
}

4 请求生命周期管理

务必在ViewModel销毁时取消所有未完成的请求,避免内存泄漏:

class DevicesViewModel(application: Application) : AndroidViewModel(application) {
    private val requestQueue = Volley.newRequestQueue(application.applicationContext)
    val items: MutableLiveData<List<Device>> by lazy {
        MutableLiveData<List<Device>>()
    }

    init {
        scanForDevices()
    }

    private fun scanForDevices() {
        val newDevices: MutableList<Device> = arrayListOf()
        for (i in 100..255) {
            val ipAddress = "192.168.2.$i"
            val url = "$ipAddress/cm?cmnd=STATUS"
            val request = StringRequest(
                Request.Method.GET, url,
                { response ->
                    // 解析响应更新newDevices,最终更新items LiveData
                },
                { error ->
                    // 处理错误逻辑
                }
            )
            // 给请求打统一标签
            request.setTag("device_scan")
            requestQueue.add(request)
        }
    }

    override fun onCleared() {
        super.onCleared()
        // ViewModel销毁时取消所有未完成的扫描请求
        requestQueue.cancelAll("device_scan")
    }
}

可选技术栈升级

如果计划重构网络层,目前Android官方更推荐使用Retrofit + OkHttp组合实现网络请求,配合Kotlin协程处理异步逻辑,代码可读性和可维护性更高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 07:30:03