都掌握了吗?Kotlin技能小成,技能掌握
都掌握了吗?Kotlin技能小成,技能掌握
前些文章描述了 Kotlin教程,包括一些基本语法。
很多时候,还需要加以练习。
本文将开发过程中,遇到的点,整理成线,继而到面
希望 把下面的问题掌握之后,掌握Kotlin在Android中的开发能力
一眼望去,立刻知道答案,Kotlin小成
1️⃣实现findViewById有几种方式?
方法一:可以更低成本从java转kotlin
@BindView(R2.id.acco_refresh_layout)
lateinit var mSmartRefreshLayout: SmartRefreshLayout
沿用ButterKnifer,可以减少从Java转Kotin的代码转换工作量。
进阶思考:为什么用lateinit?不用行不行?
方法二:使用Kotlin自带的findViewById
import kotlinx.android.synthetic.main.这里是layout的xml名字.*
acco_ll_service_info!!.visibility = View.GONE
Kotlin自带findViewById功能,acco_ll_service_info就是view在layout中的id。可以通过id直接访问。
进阶思考:Kotlin中的findViewById源码分析?
方法三:使用Android自带的findViewById
第一种写法,去掉泛型,在前面声明该控件的类型
var sml1 : SmartRefreshLayout = findViewById(R.id.acco_refresh_layout)
第二种写法,在泛型中指定该控件类型
var sml2 = findViewById<SmartRefreshLayout>(R.id.acco_refresh_layout)
这两者写法得到的sml1和sml2是一样的
2️⃣根据状态改变初始值?
lateinit var mCachedProfileBean: UserInfoResponse.DataBean
private val tradePwdStatus: String
get() = if (mCachedProfileBean?.tradePasswordStatus == UserInfoResponse.DataBean.TRADE_PWD_UN_SET) {
"未设置"
} else ""
val变量tradePwdStatus会根据mCachedProfileBean动态的改变 返回值
进阶思考:mCachedProfileBean未初始化就被访问会发生什么?
3️⃣怎么定义public static final 常量?
companion object {
private const val MSG_EXIT_APP = 1
}
这里定义了int MSG_EXIT_APP。需要放在 companion object中。
进阶思考①:伴生对象companion object适用范围,特点是什么?
进阶思考②:const与val的区别?const相当于什么?跟@JvmField的效果比较
4️⃣?. 与!!.的区别是 什么
?.表示当前对象如果为空,则返回null。
fun main() {
var numbers : List<String>?= null
println(numbers?.size?:999) //输出999
}
这个例子当numbers为null,则打印999,否则,输出numbers的size。
!!.表示当前对象为空,也继续该行语句的执行,然后会抛出NPE
fun main() {
var numbers : List<String>?= null
println(numbers!!.size?:999) //输出999
}
这个范例:会抛出KotlinNullPointerException
5️⃣lateinit标记的变量,若没初始化怎么处理?
if (!this::mCachedProfileBean.isInitialized) {
doSomething()
return
}
mCachedProfileBean需要通过this::来进行引用。
如果这个判断在内部类。还需要指定this的引用对象
if (!this@SettingsActivity::mCachedProfileBean.isInitialized) {}
lateinit跟isInitialized是 配对出现的。
变量通过lateinit标记,有初始化,可以正常使用;
没有初始化,则通过isInitialized进行判断。
通过lateinit标记的变量,在使用的时候,就需要注意其初始化状态
private val tradePwdStatus: String
get() = if (this::mCachedProfileBean.isInitialized
&& mCachedProfileBean.tradePasswordStatus == UserInfoResponse.DataBean.TRADE_PWD_UN_SET) {
"未设置"
} else ""
没加this::mCachedProfileBean.isInitialized,IDE也不会提示什么。
万一,你一个不留神,就可能会抛出kotlin.UninitializedPropertyAccessException
6️⃣内部类的使用
private inner class MyHandler(activity: Activity) : Handler() {
var mWeakReference: WeakReference<Activity> = WeakReference(activity)
override fun handleMessage(msg: Message) {
doSomething()
finish()
}
}
MyHandler继承自Handler,实现了handleMessage。
这里是通过inner来实现。假如我不用inner标记会如何?
inner内部类,隐式持有外部类的引用,可以访问外部类成员属性和成员函数。
若没有inner标记,则无法访问成员属性和成员函数。
在Kotlin的某个类中,写private class跟,新建了一个文件的效果是一样的。
7️⃣如何写一个instance函数
companion object {
fun instance(): FundsOfflineRechargeFragment {
return FundsOfflineRechargeFragment()
}
}
调用方式:
FundsOfflineRechargeFragment.instance()
8️⃣集合的创建方式
集合有3种:List、Set、Map。整理了一下,主要是这些
- List:建、增、删、查、改、排序
建:listOf
增:add、addAll
删:removeAt
查:indexOf、lastIndexOf、indexOfFirst、indexOfLast、binarySearch、
改:set、fill
排序:sort、sortDescending、sortBy、sortByDescending、sortWith、shuffle、reverse - Set:建、合并、求同、取异
建:setOf
合并:union
求同:intersect
取异:subtract - Map:建、增、删、查、改、过滤
建:mapOf
增:plus(有改的效果)、+、put、putAll、plusAssign
删:minus(有改的效果)、-、remove
查:get、getOrElse、getOrDefault
改:put、putAll
过滤:filter
9️⃣主构造函数什么时候需要显式的写?
class ViewHolder internal constructor(itemView : View): RecyclerView.ViewHolder(itemView) {
@BindView(R2.id.acco_iv_icon)
lateinit var mIconIv : ImageView
@BindView(R2.id.acco_tv_name)
lateinit var mNameTv : TextView
init {
ButterKnife.bind(this, itemView)
}
}
构造函数有注解或可见性修饰符。就需要显式的写。
初始化的代码需要放在init{}中
进阶思考:初始化能否有多个init代码块?类的初始化顺序是怎么样的?
private inner class MergeObservable(response1: BankCardListResponse, response2: UserAccountResponse) : Merge2Response<BankCardListResponse, UserAccountResponse>(response1, response2)
这里省略了 constructor
这是一个名为MergeObservable的内部类,有两个参数。
这相当于java的
private class MergeObservable extends Merge2Response<BankCardListResponse, UserAccountResponse> {
public MergeObservable(BankCardListResponse response1, UserAccountResponse response2) {
super(response1, response2);
}
}
主构函数response1、response2代表了两个参数。
后面的<BankCardListResponse, UserAccountResponse>(response1, response2),都是给父类Merge2Response的。
泛型定义传了BankCardListResponse, UserAccountResponse
参数传了response1, response2
评论暂时关闭