Android学习笔记09

把coroutines跟retrofit结合进recyclerview
这边最需要注意的是如果你retrofit拿到的值是int而不是string必须要stringvalueof(),否则android会预设为xml的数值而报错

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto">
    <data>
        <variable
            name="Post"
            type="com.example.myapplication.Post" />
        <variable
            name="viewmodel"
            type="com.example.myapplication.ViewModel" />
    </data>
    <androidx.constraintlayout.widget.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical" android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="@{()-> viewmodel.onClick(Post)}">
        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            android:padding="5dp"
            android:textSize="16sp"
            android:text="@{String.valueOf(Post.id)}" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

这边第25行就是数值转换
activity

class Activity:AppCompatActivity() {
    lateinit var binding: ActivityMainBinding

    private val mViewModel by lazy {
        initViewModel(application, ViewModel::class.java)
    }

    private val mAdapter by lazy {
        Adapter<Post>(R.layout.item_view,mViewModel)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        binding.recyclerView.adapter = mAdapter
        mViewModel.data.observe(this, Observer { post ->
            mAdapter.updateData(post)
        })
        mViewModel.coroutine()
    }
}

adapter

class Adapter<T>(
    @LayoutRes val resource: Int,
    val viewmodel:ViewModel
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    private val data: List<T>
        get() = _data.toList()
    private val _data: MutableList<T> = mutableListOf()

    fun updateData(list: ArrayList<T>){
        _data.clear()
        _data.addAll(list)
        notifyDataSetChanged()
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        val layoutInflater = LayoutInflater.from(parent.context)
        val binding = DataBindingUtil.inflate<ViewDataBinding>(layoutInflater, resource, parent,false)
        return MyViewHolder(binding)
    }

    override fun getItemCount(): Int {
        return data.size
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        if (holder is Adapter<*>.MyViewHolder){
            val item = data[position]
            if (item != null)
                holder.setupData(item)
        }

    }

    inner class MyViewHolder( var binding: ViewDataBinding):RecyclerView.ViewHolder(binding.root){
        fun setupData(post: Any){
            binding.setVariable(BR.Post, post)
            binding.setVariable(BR.viewmodel,viewmodel)
        }
    }

}

viewmodel

class ViewModel(application: Application): AndroidViewModel(application) {


    val data = MutableLiveData<ArrayList<Post>>()

    fun onClick(post: Post){
        Toast.makeText(getApplication(), post.id, Toast.LENGTH_SHORT).show()
    }

    private val myScope = object: CoroutineScope{
        override val coroutineContext: CoroutineContext
            get() = job
    }
    private val job = Job()

    fun coroutine(){
        myScope.launch(Dispatchers.Main){
//            progressBar.visibility = View.VISIBLE
            retrofit()
//            progressBar.visibility = View.GONE
        }
    }

    private suspend fun retrofit() = withContext(Dispatchers.IO){
        val response = GoRetrofit.api.getAPI()
        if (response.isSuccessful) {
            data.postValue(response.body() as ArrayList<Post>)
        }
    }

    override fun onCleared() {
        myScope.cancel()
        super.onCleared()
    }

}

这边要注意的是postvalue(),如果在main线程是可以使用setvalue(),但如过是在用後台线程就必须要用postvalue()


<<:  Day18-React起步

>>:  Day03:【TypeScript 学起来】自动编译 tsc + nodemon 好方便

从 React 开始,让你的网页material-ui起来 [Day 2] 差异性安装

如需在地端环境操作 那需要去理解 什麽是node JS 什麽是NPM 需要参照 本地安装 使用 np...

JWT实作(五)(Day9)

讲到权限之前,我们必须谈谈spring security的Filter Chain(过滤器链) Ke...

Day28 资料流重新导向I

今天要来介绍的部分是资料流重新导向的部分,这个东西其实就是字面上的意思,就是将某个指令成功执行後所要...

33岁转职者的前端笔记-DAY 6 CSS button 套件

最近的工作专案很常用到 button 按钮 因为小公司的关系没有设计 所以通常要自已想 button...

【Day 19】 实作 - 透过 AWS 服务 Glue Job 调整 Partition 以及档案格式

昨天我们已经透过 AWS Glue Crawler 自动建立 VPC Log 资料表,并且我们也看到...