一眼望去,立刻知道答案,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中怎么进行运算:加减乘除余等
1️⃣实现findViewById有几种方式?
方法一:可以更低成本从java转kotlin
@BindView(R2.id.acco_refresh_layout)
lateinit var mSmartRefreshLayout: SmartRefreshLayout
- 1
- 2
沿用ButterKnifer,可以减少从Java转Kotin的代码转换工作量。
进阶思考:为什么用lateinit?不用行不行?
方法二:使用Kotlin自带的findViewById
import kotlinx.android.synthetic.main.这里是layout的xml名字.*
acco_ll_service_info!!.visibility = View.GONE
- 1
- 2
- 3
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)
- 1
- 2
- 3
- 4
- 5
这两者写法得到的sml1和sml2是一样的
2️⃣根据状态改变初始值?
lateinit var mCachedProfileBean: UserInfoResponse.DataBean
private val tradePwdStatus: String
get() = if (mCachedProfileBean?.tradePasswordStatus == UserInfoResponse.DataBean.TRADE_PWD_UN_SET) {
"未设置"
} else ""
- 1
- 2
- 3
- 4
- 5
- 6
val变量tradePwdStatus会根据mCachedProfileBean动态的改变 返回值
进阶思考:mCachedProfileBean未初始化就被访问会发生什么?
3️⃣怎么定义public static final 常量?
companion object {
private const val MSG_EXIT_APP = 1
}
- 1
- 2
- 3
这里定义了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
}
- 1
- 2
- 3
- 4
这个例子当numbers为null,则打印999,否则,输出numbers的size。
!!.表示当前对象为空,也继续该行语句的执行,然后会抛出NPE
fun main() {
var numbers : List<String>?= null
println(numbers!!.size?:999) //输出999
}
- 1
- 2
- 3
- 4
这个范例:会抛出KotlinNullPointerException
5️⃣lateinit标记的变量,若没初始化怎么处理?
if (!this::mCachedProfileBean.isInitialized) {
doSomething()
return
}
- 1
- 2
- 3
- 4
mCachedProfileBean需要通过this::来进行引用。
如果这个判断在内部类。还需要指定this的引用对象
if (!this@SettingsActivity::mCachedProfileBean.isInitialized) {}
- 1
lateinit跟isInitialized是 配对出现的。
变量通过lateinit标记,有初始化,可以正常使用;
没有初始化,则通过isInitialized进行判断。
通过lateinit标记的变量,在使用的时候,就需要注意其初始化状态
private val tradePwdStatus: String
get() = if (this::mCachedProfileBean.isInitialized
&& mCachedProfileBean.tradePasswordStatus == UserInfoResponse.DataBean.TRADE_PWD_UN_SET) {
"未设置"
} else ""
- 1
- 2
- 3
- 4
- 5
没加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()
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
MyHandler继承自Handler,实现了handleMessage。
这里是通过inner来实现。假如我不用inner标记会如何?
inner内部类,隐式持有外部类的引用,可以访问外部类成员属性和成员函数。
若没有inner标记,则无法访问成员属性和成员函数。
在Kotlin的某个类中,写private class跟,新建了一个文件的效果是一样的。
7️⃣如何写一个instance函数
companion object {
fun instance(): FundsOfflineRechargeFragment {
return FundsOfflineRechargeFragment()
}
}
调用方式:
FundsOfflineRechargeFragment.instance()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
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)
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
构造函数有注解或可见性修饰符。就需要显式的写。
初始化的代码需要放在init{}中
进阶思考:初始化能否有多个init代码块?类的初始化顺序是怎么样的?
private inner class MergeObservable(response1: BankCardListResponse, response2: UserAccountResponse) : Merge2Response<BankCardListResponse, UserAccountResponse>(response1, response2)
- 1
这里省略了 constructor
这是一个名为MergeObservable的内部类,有两个参数。
这相当于java的
private class MergeObservable extends Merge2Response<BankCardListResponse, UserAccountResponse> {
public MergeObservable(BankCardListResponse response1, UserAccountResponse response2) {
super(response1, response2);
}
}
- 1
- 2
- 3
- 4
- 5
主构函数response1、response2代表了两个参数。
后面的<BankCardListResponse, UserAccountResponse>(response1, response2),都是给父类Merge2Response的。
泛型定义传了BankCardListResponse, UserAccountResponse
参数传了response1, response2
?注意this return break continue配合@label的使用
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<Boolean> { granted ->
doSomething()
})
} else {
getPhotoDialog().show()
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
标签label会引向特定的位置或对象。
?1️⃣数据类怎么写
data class QualifyInvestorBean(val index: Int, val icon: Int, val investorStatus: String, var dataManageType: String)
- 1
用data修饰class;
参数:标注var、val
类型:用符号:标注 类型
?2️⃣let、run、with、apply、also的速记整理
?3️⃣在kotlin中怎么进行运算:加减乘除余等
在Kotlin中,万物皆对象。在进行java、kotlin混编的时候,遇到尴尬
None of the following functions can be called with the arguments supplied.
原因:在运算中,kotlin不会自动转换这些数值的类型,而在java中使用是没有问题的,因为java会自动帮你转换。
所以,还是 类型声明
的问题。
拿截图中的范例来说,java应该是这样的
return * (1 - Integer.valueOf(findTransferRatio().getValue()).intValue() / 100.f) - (mResponseContent.getData().isDeduction() == 1 ? mResponseContent.getData().getAlreadyRepaidYieldBalance() : 0);
- 1
转换成kotlin
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
- 1
- 2
- 3
- 4
- 5
类型转换问题,就需要手动更为精确的进行转换。
在kotlin中,对没个运算参数都需要确认格式。
本例中,这样拆分之后,就很清楚了
小结
是的~~~~
反射没写、。
嗯嗯嗯~~~~这些了这么多,因为IDE也会有warning提示。改掉之后就基本清晰了。
掌握了这些基本可以做业务开发
了。
欢迎大家帮忙补充~~~~