【发布时间】:2021-11-07 12:53:58
【问题描述】:
我的目标是在 recyclerview 中显示 HTTP 请求的结果。因为我有一段时间没有使用 Android,所以我想使用最喜欢的方法。
我有一个设备数据类:
data class Device(val name: String, val ipAddress: String, val type: String = "")
一个新设备适配器:
class NewDevicesAdapter(private val items: List<Device>) :
RecyclerView.Adapter<NewDevicesAdapter.ViewHolder>() {
lateinit var binding: AdapterNewDevicesBinding
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
ViewHolder(
AdapterNewDevicesBinding.inflate(LayoutInflater.from(parent.context))
)
override fun onBindViewHolder(holder: ViewHolder, position: Int) = holder.bind(items[position])
override fun getItemCount(): Int = items.size
inner class ViewHolder(val binding: AdapterNewDevicesBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(item: Device) {
binding.device = item
}
}
}
使用 xml:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="device"
type="[...].Device" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
[...]
<TextView
android:id="@+id/adapter_newDevices_textView_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{device.name}" />
<TextView
android:id="@+id/adapter_newDevices_textView_ip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{device.ipAddress}" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
还有一个 NewDeviceFragment 类:
class NewDeviceFragment : Fragment() {
private lateinit var binding: FragmentNewDeviceBinding
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
}
[...]
binding.devicesViewModel!!.items.observe(viewLifecycleOwner, Observer { response ->
binding.newDeviceRecyclerViewDevices.adapter = NewDevicesAdapter(response as List<Device>)
})
return binding.root
}
使用 xml:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="devicesViewModel"
type="[...].DevicesViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
[...]
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/newDevice_recyclerView_devices"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/adapter_new_devices"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/newDevice_toolbar" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
我有一个 ViewModel 类,它应该通过 HTTP 请求收集数据,然后将其存储在 LiveData 对象中,以通过片段中的观察者显示在 recyclerview 中:
class DevicesViewModel: ViewModel() {
val items: MutableLiveData<List<Device>> by lazy {
MutableLiveData<List<Device>>()
}
init {
scanForDevices()
}
private fun scanForDevices() = {
val newDevices: MutableList<Device> = arrayListOf()
val queue = Volley.newRequestQueue()
for (i in 100..255) {
val ipAddress = "192.168.2.$i"
val url = "$ipAddress/cm?cmnd=STATUS"
[...]
}
}
但是对于 Volley RequestQueue,我需要 ViewModel 中不存在的上下文。现在我听说过 AndroidViewModel,但我不确定这是否是正确的方法。也许有人可以给我一个建议,我可以/应该如何通过 HTTP 请求和 Recyclerview 中的结果最好地实现这个概念。
【问题讨论】:
-
使用 AndroidViewModel 绝对没问题,或者您可以使用 Hillt 这是一个 DI 框架并在 ViewModel 中注入上下文,这也是一个可行的解决方案
标签: android kotlin data-binding android-volley viewmodel