前些文章描述了 Kotlin教程,包括一些基本语法。
很多时候,还需要加以练习。
本文将开发过程中,遇到的点,整理成线,继而到面
希望 把下面的问题掌握之后,掌握Kotlin在Android中的开发能力
一眼望去,立刻知道答案,Kotlin小成
1️⃣实现findViewById有几种方式?
进阶思考:Kotlin中的findViewById源码分析?
2️⃣根据状态改变初始值?
进阶思考:mCachedProfileBean未初始化就被访问会发生什么?
3️⃣怎么定义public static final 常量?
进阶思考①:伴生对象companion object适用范围,特点是什么?`
进阶思考②:const与val的区别?const相当于什么?跟@JvmField的效果比较
4️⃣?. 与!!.的区别是 什么
5️⃣lateinit标记的变量,若没初始化怎么处理?
6️⃣内部类的使用
7️⃣如何写一个instance函数
8️⃣集合的有哪些操作函数
9️⃣主构造函数什么时候需要显式的写?
进阶思考:初始化能否有多个init代码块?类的初始化顺序是怎么样的?
?注意this return break continue配合@label的使用
?1️⃣数据类怎么写
?2️⃣let、run、with、apply、also的速记整理
?3️⃣在kotlin中怎么进行运算:加减乘除余等
方法一:可以更低成本从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(R.id.acco_refresh_layout)
这两者写法得到的sml1和sml2是一样的
lateinit var mCachedProfileBean: UserInfoResponse.DataBean
private val tradePwdStatus: String
get() = if (mCachedProfileBean?.tradePasswordStatus == UserInfoResponse.DataBean.TRADE_PWD_UN_SET) {
"未设置"
} else ""
val变量tradePwdStatus会根据mCachedProfileBean动态的改变 返回值
进阶思考:mCachedProfileBean未初始化就被访问会发生什么?
companion object {
private const val MSG_EXIT_APP = 1
}
这里定义了int MSG_EXIT_APP。需要放在 companion object中。
进阶思考①:伴生对象companion object适用范围,特点是什么?
进阶思考②:const与val的区别?const相当于什么?跟@JvmField的效果比较
?.表示当前对象如果为空,则返回null。
fun main() {
var numbers : List?= null
println(numbers?.size?:999) //输出999
}
这个例子当numbers为null,则打印999,否则,输出numbers的size。
!!.表示当前对象为空,也继续该行语句的执行,然后会抛出NPE
fun main() {
var numbers : List?= null
println(numbers!!.size?:999) //输出999
}
这个范例:会抛出KotlinNullPointerException
if (!this::mCachedProfileBean.isInitialized) {
doSomething()
return
}
mCachedProfileBean需要通过this::来进行引用。
如果这个判断在内部类。还需要指定this的引用对象
if (!this@SettingsActivity::mCachedProfileBean.isInitialized) {}
lateinit跟isInitialized是 配对出现的。
变量通过lateinit标记,有初始化,可以正常使用;
没有初始化,则通过isInitialized进行判断。
private val tradePwdStatus: String
get() = if (this::mCachedProfileBean.isInitialized
&& mCachedProfileBean.tradePasswordStatus == UserInfoResponse.DataBean.TRADE_PWD_UN_SET) {
"未设置"
} else ""
没加this::mCachedProfileBean.isInitialized,IDE也不会提示什么。
万一,你一个不留神,就可能会抛出kotlin.UninitializedPropertyAccessException
private inner class MyHandler(activity: Activity) : Handler() {
var mWeakReference: WeakReference = WeakReference(activity)
override fun handleMessage(msg: Message) {
doSomething()
finish()
}
}
MyHandler继承自Handler,实现了handleMessage。
这里是通过inner来实现。假如我不用inner标记会如何?
inner内部类,隐式持有外部类的引用,可以访问外部类成员属性和成员函数。
若没有inner标记,则无法访问成员属性和成员函数。
在Kotlin的某个类中,写private class跟,新建了一个文件的效果是一样的。
companion object {
fun instance(): FundsOfflineRechargeFragment {
return FundsOfflineRechargeFragment()
}
}
调用方式:
FundsOfflineRechargeFragment.instance()
集合有3种:List、Set、Map。整理了一下,主要是这些
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代码块?类的初始化顺序是怎么样的?
private inner class MergeObservable(response1: BankCardListResponse, response2: UserAccountResponse) : Merge2Response(response1, response2)
这里省略了 constructor
这是一个名为MergeObservable的内部类,有两个参数。
private class MergeObservable extends Merge2Response {
public MergeObservable(BankCardListResponse response1, UserAccountResponse response2) {
super(response1, response2);
}
}
主构函数response1、response2代表了两个参数。
后面的
泛型定义传了BankCardListResponse, UserAccountResponse
参数传了response1, response2
addNewBinder.setOnItemClickListener{holder, item, position ->
if (mClientSn == 0) {
requestInitInfo()
return@setOnItemClickListener
}
val hasWritePermission = ContextCompat.checkSelfPermission(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
if (!hasWritePermission) {
val rxPermissions = RxPermissions(this@AssetProofManageActivity)
rxPermissions.request(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA).subscribe(Consumer { granted ->
doSomething()
})
} else {
getPhotoDialog().show()
}
}
标签label会引向特定的位置或对象。
data class QualifyInvestorBean(val index: Int, val icon: Int, val investorStatus: String, var dataManageType: String)
用data修饰class;
参数:标注var、val
类型:用符号:标注 类型
在Kotlin中,万物皆对象。在进行java、kotlin混编的时候,遇到尴尬
None of the following functions can be called with the arguments supplied.
原因:在运算中,kotlin不会自动转换这些数值的类型,而在java中使用是没有问题的,因为java会自动帮你转换。
所以,还是 类型声明
的问题。
return * (1 - Integer.valueOf(findTransferRatio().getValue()).intValue() / 100.f) - (mResponseContent.getData().isDeduction() == 1 ? mResponseContent.getData().getAlreadyRepaidYieldBalance() : 0);
val quantity : Double = (mResponseContent?.data?.quantity?:0).toDouble()
val ratio : Double = 1 - (findTransferRatio()?.value?.toInt()?:0)/100.0
val alreadyYieldBalance : Double = if (mResponseContent?.data?.isDeduction == 1) mResponseContent?.data?.alreadyRepaidYieldBalance?:0.0 else 0.0
return quantity * ratio - alreadyYieldBalance
类型转换问题,就需要手动更为精确的进行转换。
在kotlin中,对没个运算参数都需要确认格式。
本例中,这样拆分之后,就很清楚了
是的~~~~
反射没写、。
嗯嗯嗯~~~~这些了这么多,因为IDE也会有warning提示。改掉之后就基本清晰了。
掌握了这些基本可以做业务开发
了。
欢迎大家帮忙补充~~~~