简介
主要会通过安卓实战来讲解kotlin语法和实际应用,本教程设及知识点包括框架模式mvp+mvvm, Databinding(数据绑定框架),Dagger2(依赖注入框架),DeepLink(页面路由框架),Rxjava,RxAndroid(异步操作框架),Retrofit,Okhtttp等,不过本教程重点在kotlin所以这些框架需要了解可自行百度。
针对人群:Android中级以上,kotlin入门
本系列最后一篇我们看看recyclerView的adapter怎么实现的
首先先看一下代码
/**
* Created by bigman on 18-05-18.
*/
class AndroidAdapter(private val mList: List<AndroidBean>)
:BaseBindingAdapter<ItemAndroidBinding>() {
override fun getItemCount(): Int {
return mList.size
}
override fun onBindViewHolder(holder: DataBoundViewHolder<ItemAndroidBinding>, position: Int) {
super.onBindViewHolder(holder, position)
//数据绑定
holder.binding.androidbean = mList[position]
//数据立即绑定而不是在下一帧的时候才绑定,避免闪烁和数据错乱
holder.binding.executePendingBindings()
}
override fun onCreateViewHolder(parent: ViewGroup,
viewType: Int): DataBoundViewHolder<ItemAndroidBinding> {
return DataBoundViewHolder(
ItemAndroidBinding.inflate(LayoutInflater.from(parent.context), parent, false))
}
}
首先看主构造函数和继承
class AndroidAdapter(private val mList: List<AndroidBean>)
:BaseBindingAdapter<ItemAndroidBinding>()
- 主构造函数传入一个
List<AndroidBean>
类型的mList
只读变量 - 继承至
BaseBindingAdapter<ItemAndroidBinding>()
下一步我们看一下基类BaseBindingAdapter
的具体实现
/**
* Created by bigman on 18-05-18.
*/
abstract class BaseBindingAdapter<B : ViewDataBinding>
: RecyclerView.Adapter<DataBoundViewHolder<B>>() {
var mListener: ((pos: Int) -> Unit)? = null
override fun onBindViewHolder(holder: DataBoundViewHolder<B>, position: Int) {
holder.binding.root.setOnClickListener {
mListener?.invoke(holder.adapterPosition)
}
}
fun setOnItemClickListener(listener: ((pos: Int) -> Unit)) {
mListener = listener
}
}
- 大家可以看到
BaseBindingAdapter
需要传入ViewDataBinding
类型,这个ViewDataBinding
是databinding里面所有视图bingding类的基类, - 然后毫无疑问它必须继承于
RecyclerView.Adapter<DataBoundViewHolder<B>>
,这个我们平时写java的RecyclerView.Adapter的时候都需要继承的
这里还有一个DataBoundViewHolder<B>
,看一下代码实现
/**
* Created by bigman on 18-05-18.
*/
class DataBoundViewHolder<T : ViewDataBinding>(val binding:T)
: RecyclerView.ViewHolder(binding.root) {
}
其实它就是一个RecyclerView.ViewHolder
,只是这里我们传入了通用的ViewDataBinding
使它变成可以绑定任意视图
回到BaseBindingAdapter
,这个基类主要功能就是实现一个通用的databinding用的适配器,只要传入databinding视图类型即可,类内部提供了一个点击事件的回调方法
然后再回到AndroidAdapter
这里主要由三个方法,
-
getItemCount ()
返回绑定列表长度, -
onBindViewHolder ()
实现视图数据绑定,这里用的databingding的数据绑定,holder.binding.executePendingBindings()
,这句代码比较重要不加可能导致数据错乱或者页面闪烁 -
onCreateViewHolder()
主要是完成databinding的holder构建
override fun onCreateViewHolder(parent: ViewGroup,
viewType: Int): DataBoundViewHolder<ItemAndroidBinding> {
return DataBoundViewHolder(
ItemAndroidBinding.inflate(LayoutInflater.from(parent.context), parent, false))
}
这里的 ItemAndroidBinding
是databinding根据我们的布局文件自动生成的,我们看一下我们这个列表条目布局代码,名称item_android.xml注意对比databinding生成的binding类名称
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="android.view.View" />
<variable
name="androidbean"
type="com.bigman.kotlin.bean.AndroidBean" />
</data>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_marginLeft="2dp"
android:layout_marginRight="2dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:background="#fff"
android:orientation="vertical"
app:cardCornerRadius="5dp"
android:paddingTop="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="vertical"
android:paddingLeft="16dp"
android:paddingBottom="10dp"
android:paddingRight="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{androidbean.desc}"
android:textColor="#000"
android:textSize="16sp" />
<ImageView
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_marginTop="10dp"
android:scaleType="center"
android:visibility="@{androidbean.hasImg()?View.VISIBLE:View.GONE}"
app:load_image="@{androidbean.images[0]}" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_marginTop="10dp"
android:text="@{androidbean.who}"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
/>
<TextView
android:layout_marginTop="10dp"
android:text = "@{androidbean.create()}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
</layout>
具体代码和前面说过的布局没啥太大区别,主要就是data数据的传入和数据绑定
眼神比较犀利的同学可能会看到几个比较不一样的地方而存在疑惑,我们看看是哪里
<ImageView
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_marginTop="10dp"
android:scaleType="center"
android:visibility="@{androidbean.hasImg()?View.VISIBLE:View.GONE}"
app:load_image="@{androidbean.images[0]}" />
这里的app:load_image
这是''databinding允许的一个函数绑定形式
我们看一下具体实现:
/**
* Created by bigman on 18-05-18.
*/
@BindingAdapter("load_image")
fun loadImage(imageView: ImageView, url: String?) =
Glide.with(imageView.context).load(url)
.crossFade()
.into(imageView)
@BindingAdapter("set_text")
fun setText(textView: TextView, string: String) {
textView.setText("bigman" + string)
}
@BindingAdapter("load_asset")
fun loadAsset(imageView: ImageView, id: Int) =
Glide.with(imageView.context).load(id).into(imageView)
这几个函数被我卸载随意的一个kt文件里面,然后通过 @BindingAdapter
注解,我们的databinding框架就能很容易的找到它
那么我们这一系列kotlin 安卓实战内容到这里结束了,虽然kotlin知识点讲的不错,但是基本的运用知道这些也差不多够了,大家可以自己动手写一下,本系列主要目的已经达到,就是kotlin在这种mvp+mvvm目前最合理框架上的具体应用