Kotlin学习系列——技能小成

一眼望去,立刻知道答案,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提示。改掉之后就基本清晰了。
掌握了这些基本可以做业务开发了。

欢迎大家帮忙补充~~~~

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Kotlin是一种现代化的静态类型编程语言,它可以在Java虚拟机(JVM)上运行,并且与Java语言高度兼容。如果你想学习Kotlin,以下是一个学习路线的建议: 1. 了解基础知识:开始学习Kotlin之前,建议先了解一些基本的编程概念和语法,比如变量、数据类型、条件语句、循环语句等。这将为你后续的学习打下坚实的基础。 2. 学习Kotlin语法:Kotlin与Java有很多相似之处,但也有一些不同之处。学习Kotlin的语法和特性,比如空安全、扩展函数、数据类等,可以通过官方文档、教程或在线课程来学习。 3. 实践编程:通过编写一些简单的程序来巩固所学的知识。可以尝试解决一些小问题或者完成一些小项目,这样可以更好地理解和应用Kotlin的语法和特性。 4. 深入学习面向对象编程:Kotlin是一种面向对象的编程语言,深入学习面向对象编程的概念和原则对于掌握Kotlin非常重要。学习类、对象、继承、多态等概念,并尝试在Kotlin中应用这些概念。 5. 学习Kotlin与Java的互操作性:由于Kotlin与Java高度兼容,学习如何在Kotlin中使用Java类库和框架是非常重要的。了解如何调用Java代码、处理Java集合等,可以帮助你更好地使用Kotlin进行开发。 6. 深入学习Kotlin的高级特性:一旦掌握了Kotlin的基础知识,可以进一步学习一些高级特性,比如协程、函数式编程、DSL等。这些特性可以提高你的代码质量和开发效率。 7. 参与实际项目:最好的学习方式是通过实践。尝试参与一些实际的项目或者开源项目,与其他开发者合作,这样可以提升你的编程能力和实践经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值