Kotlin相对于Java来说,代码量减少很多,代码变得更简洁了,况且Kotlin现在由Google负责,在Andorid上作为主推语言,所以Kotlin的发展前景还是不可限量的。
Kotlin的基本语法就不做介绍了,网上也有很多优秀的博客,请自行搜索.今天就重点介绍Kotlin+MVP+RecyclerView的使用。
Activity中初始化
在xml中定义好控件设定好id后,在Activity中直接使用
/**
* 设置按钮的点击事件
*/
fun initView() {
//直接使用控件id设置监听
btn1.setOnClickListener {
click1()
}
btn2.setOnClickListener(this)
}
/**
* 点击事件
* 批量处理,通过when函数
*/
override fun onClick(v: View?) {
when (v?.id) {
R.id.btn2 -> click2()
else -> {
//失败处理
}
}
}
点击事件里的具体实现稍后再看,现在先看下initPresenter函数
/**
* 延迟加载
* lateinit:只能用在var类型,可初始化多次,延迟加载
*/
private lateinit var presenter: RegisterContract.Presenter
/**
* 初始化Presenter
* 把RegisterContract.View、Context传进入
*/
fun initPresenter() {
//创建Presenter对象
presenter = RegisterPresenter(this, this)
}
点击事件click1函数实现
/**
* 创建对象并提交信息
*/
fun click1() {
//直接通过 对象() 创建对象
var userInfo = UserInfo()
userInfo.name = "xiaoming"
userInfo.sex = "woman"
userInfo.num = 25
userInfo.height = 178
//提交对象信息
presenter.submitRegisterInfo(userInfo)
}
从click1函数可以发现,创建对象没有 “new” 关键字,直接 “对象()” 就可以。
以上代码是不是感觉少了点什么,没错!逗号不需要写了。
具体的MVP代码
协调器RegisterContract
和java区别不大,只是参数变成了(变量名:类型)、修饰符变成 fun
/**
* Created by yunzhao.liu on 2018/3/7
*/
interface RegisterContract {
/**
* 负责更新Activity的UI
*/
interface View {
fun registerSuccess(info: String)
fun registerFailure(msg: String)
}
/**
* 连接View和Model的桥梁
*/
interface Presenter {
fun submitRegisterInfo(info: UserInfo)
}
/**
* 负责提供数据
*/
interface Model {
fun getRegisterInfo(info: UserInfo, listener: OnListener)
}
}
连接View和Model桥梁的RegisterPresenter
class RegisterPresenter : RegisterContract.Presenter {
private var view: RegisterContract.View
private var context: Context
private var mode: RegisterMode
/**
* Presenter的构造函数
*/
constructor(view: RegisterContract.View, context: Context) {
this.view = view
this.context = context
//创建RegisterMode对象
this.mode = RegisterMode()
}
/**
* 提交注册信息
*/
override fun submitRegisterInfo(info: UserInfo) {
mode.getRegisterInfo(
info, object : OnListener {//匿名接口
override fun onSuccess(response: String?) {
//!!为空判断,如果是null就返回null
view.registerSuccess(response!!)
}
override fun onFailure(msg: String?) {
if (msg != null) {
view.registerFailure(msg)
}
}
}
)
}
}
提供数据的RegisterMode
/**
* Created by yunzhao.liu on 2018/3/7
*/
class RegisterMode : RegisterContract.Model {
/**
* 获取注册数据
*/
override fun getRegisterInfo(info: UserInfo, listener: OnListener) {
listener.onSuccess("姓名:${info.name} "
+ "- 年龄:${info.age}"
+ "- 身高:${info.height}"
+ "- 性别:${info.sex}"
+ "- 班号:${info.num}")
Handler().postDelayed(Runnable {
listener.onFailure("failure")
}, 3000)
}
}
在Activity中实现 RegisterContract.View 的方法
override fun registerSuccess(info: String) {
toast(info)
}
override fun registerFailure(msg: String) {
toast(msg)
}
toast是什么鬼?稍后解释
具体Kotlin+RecyclerView代码
下面重点来看下Kotlin与RecyclerView的使用
/**
* 初始化RecyclerView相关数据
*/
fun initRecyclerViewData() {
//获取列表数据
val list = getList()
//创建Adapter对象
var adapter = RegisterAdapter(this, list)
//给RecyclerView设置Adater
recycler_view.adapter = adapter
//设置LayoutManager
recycler_view.layoutManager = (LinearLayoutManager(this))
//RecyclerView条目点击(自定义回调函数)
adapter.setOnItemClickLitener(object : RegisterAdapter.OnItemClickListener{
override fun onItemClick(position: Int) {
toast("点击位置是:$position")
}
})
}
定义 RegisterAdapter 类
注释很清楚了,就不多做解释了
/**
* Created by yunzhao.liu on 2018/3/7
*/
class RegisterAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder> {
private var context: Context
private var list: ArrayList<Product>
private var inflater: LayoutInflater
constructor(context: Context, list: ArrayList<Product>) {
this.context = context
this.list = list
this.inflater = from(context)
}
/**
* 条目数
*/
override fun getItemCount(): Int {
//为空就返回0
return list?.size
}
/**
* 获取布局类型
*/
override fun getItemViewType(position: Int): Int {
val product: Product = list.get(position)
when (product.type) {
2 -> return 2
4, 5, 8 -> return 2
else -> {
return 1
}
}
}
/**
* 创建多布局ViewHolder
*/
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): RecyclerView.ViewHolder {
return when (viewType) {
1 -> {
OneViewHolder(inflater.inflate(R.layout.recycler_item_one, parent, false))
}
2 -> {
TwoViewHolder(inflater.inflate(R.layout.recycler_item_two, parent, false))
}
else -> {
OneViewHolder(inflater.inflate(R.layout.recycler_item_one, parent, false))
}
}
}
/**
* 绑定ViewHolder
*/
override fun onBindViewHolder(holder: RecyclerView.ViewHolder?, position: Int) {
val product = list[position]
//获取条目类型
when(getItemViewType(position)){
2,4,5,8->{
//强势转换 as ,安全转换 as?, 类型判断:is
var twoViewHolder:TwoViewHolder = holder as TwoViewHolder
twoViewHolder.name.text = product.name
twoViewHolder.price.text = "${product.price}"
twoViewHolder.item_root.setOnClickListener {
itemClick!!.onItemClick(position)
}
}
else ->{
var oneViewHolder:OneViewHolder = holder as OneViewHolder
oneViewHolder.name.text = product.name
oneViewHolder.price.text = product.price.toString()
oneViewHolder.item_root.setOnClickListener {
itemClick!!.onItemClick(position)
}
}
}
}
/**
* 获取控件ID --> 一种方式
*/
class OneViewHolder(view:View):RecyclerView.ViewHolder(view){
var item_root:LinearLayout = view.item_root
var name:Button = view.name
var price:Button = view.price
}
/**
* 获取控件ID --> 一种方式
*/
class TwoViewHolder : RecyclerView.ViewHolder{
var item_root:LinearLayout
var name:Button
var price:Button
constructor(view: View) : super(view){
name = view.name
price = view.price
item_root= view.item_root
}
}
/**
* 条目点击 --> 接口回调
*/
private var itemClick: OnItemClickListener?=null
interface OnItemClickListener{
fun onItemClick(position: Int)
}
fun setOnItemClickLitener(itemClick: OnItemClickListener) {
this.itemClick = itemClick
}
}
扩展函数
在上面细心的同学已经看见了,我们使用toast(mag:String)这个方法,它就是我们定义的扩展函数。我们只需要创建一个Koltin的类,然后按照下面这种格式就可以自定义自己的扩展函数
fun 函数扩展的对象.扩展函数的名称(扩展函数的参数,可以为null){
body
}
这是我自定义的扩展函数
/**
* 对Context的扩展函数
*/
fun Context.toast(message: String, duration: Int = Toast.LENGTH_SHORT) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
/**
* 对Log的扩展函数
*/
fun Log.log(message: String) {
Log.d("liuyz", message)
}
/**
* 对Log的扩展函数
*/
fun Log.log(tag: String = "liuyz", message: String) {
Log.d(tag, message)
}
/**
* 对EditText监听的扩展
*/
fun EditText.setTextChangedListener(body: (key: String) -> Unit) {
addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
body(s.toString())
}
})
}