1.kotlin 顶层函数
函数可以不必须在类中创建,方便在java中调用,可以为其加注解类名:
示例:
顶层函数
@file:JvmName("DisplayUtils")
package com.zhboy.factoryaddemo
fun getScreenWidth():Int{
return 720
}
Java中调用
package com.zhboy.factoryaddemo;
class MainActivity1 {
public static void main(String[] args) {
DisplayUtils.getScreenWidth();
}
}
2.kotlin中?的作用
来表示变量可能为空的,Java中也有类似作用的东西,@Nullable注解
3.kotlin中的lateinit作用
用来做延迟初始化,但只能修饰非基本类型
4.Java中的class文件,在Kotlin如何表示
示例:
startActivity(this,SecondActivity::class.java)
5.kotlin的静态函数如何定义
使用顶层函数、object类(创建了一个单例对象,其中属性和对象均可直接调用)
6.kotlin中的companion作用使用场景
伴生对象。一般用于静态内部类 companion object{},
外部调用需要先拿到companion对象,如果想直接获取到可以用@JvmStatic注解
示例:
class MyClass {
companion object {
@JvmStatic
fun aStaticFuncation (){}
}
}
7.什么是受检异常?kotlin中是否存在?
Kotlin中没有,Java有受检异常(受检异常:必须进行try..catch)
8.Java中如何声明注解
Kotlin中是annotation class声明注解
9.Kotlin中internal的作用
模块内可见修饰符,即当前moudle中可见,其他moudle不可见。做sdk开发时常用。
10.什么是Kotlin主构造函数?只有主构造函数如何厨师换变量
主构造函数:就是将构造函数声明写到类上声明。
对于只有主构造函数的类,初始化变量可以使用init代码块。
另外kotlin在编译的时候会,将init代码块的代码和类成员属性按定义的顺序合并。
示例:
class Picture(var name: String, var age: Int) {
//创建一个画笔
private var paint = paint()
init {
paint.style = Paint.style.STROKE
println("main constructor init")
}
//次构造函数
constructor(name: String, age: Int, sex: String) : this(name, age) {
}
//次构造函数
constructor(name: String, age: Int, sex: String, idCard: String) : this(name, age, sex) {
}
}
11.Kotlin中data修饰符作用
当 class 中的data的存在时,Kotlin会自动生成以下函数
equals()
hashCode()
toString()
componentN()
copy()
但是当有data是,不能是无参构造函数。
示例:
data class Country(var id: Int, var name: String, var continent: String)
12.kotlin中==和===的作用和区别
kotlin中==其实是.equel,比较的数值是否相等,===比较的是内存地址
当对象使用.copy时,数值是相同,内存地址是不同的
13.如何查看kotlin对应的java代码和生成字节码
使用Android Studio
Tools -> Kotlin -> Show Kotlin Bytecode
14.kotlin中的解构
可以直接拿到对应的对象属性,如何生成解构,对象上点击右键,选择Use destructuring declaration,如下图:
示例:
package com.zhboy.factoryaddemo
/**
* @author: zhou_hao
* @date: 2020/11/26
* @description:kotlin中解构的使用示例
**/
/**
* 声明实体对象
*/
data class Person(var name: String, var age: Int)
/**
* 根据业务创建一个人
*/
fun createOnePerson(): Person {
/*
处理完一系列业务逻辑给name赋值为 "小明",age 赋值为 "18"
*/
return Person("小明", 18)
}
fun main() {
/*
这里就是解构,可以直接拿到对应的对象属性
*/
val (name, age) = createOnePerson()
print("用户名:${name} 用户年龄:${age}岁")
}
15. kotlin中的operator修饰符
定义是运算符重载,作用是对已有的运算符赋予新的定义
示例:
package com.zhboy.factoryaddemo
/**
* @author: zhou_hao
* @date: 2020/11/26
* @description:kotlin中operator作用
**/
/**
* 声明实体对象
*/
data class Person1(var name: String, var age: Int)
operator fun Int.plus(p: Person1): Int {
return this - p.age
}
fun main() {
val p = Person1("小明",18)
val tInt = 10
print("相加${p.age-tInt}")
//结果是8
}
16.kotlin方法嵌套
内部方法,可以调用外部方法,也可以调用class类方法。但当前类或者外部类不可访问
warning:内部函数每次都会生成一个对象,所以不合适放到循环中使用
示例:
package com.zhboy.factoryaddemo
/**
* @author: zhou_hao
* @date: 2020/11/26
* @description:方法嵌套方法
**/
class TestFunInFun() {
private val name = "小明"
private fun outFun(outName: String): Boolean {
fun inFun(name: String): Boolean {
return outName == name
}
return inFun(this.name)
}
}
17.JvmOverloads的作用
当java调用kotlin代码时,有些地方会有不同,比如kotlin定义参数默认值,kotlin可以直接调用,但Java会只生成多参数的方法。
@JvmOverloads的作用就是兼容Java,如果纯kotlin就可以不需要
示例:
package com.zhboy.factoryaddemo
import android.widget.Toast
import java.time.Duration
/**
* @author: zhou_hao
* @date: 2020/11/26
* @description:JvmOverloads作用
**/
object JvmOverloadsTest {
@JvmOverloads
@JvmStatic
fun toast(string: String?,duration: Int = Toast.LENGTH_LONG){
Toast.makeText(appContext,string,duration).show()
}
}
18.kotlin扩展
作用是可以对一个类的属性和方法进行扩展。是在编译的时候生成的静态方法,将对应的对象作为参数。
示例:
package com.zhboy.factoryaddemo
import android.content.res.Resources
import android.util.TypedValue
/**
* @author: zhou_hao
* @date: 2020/11/26
* @description:kotlin 扩展
**/
/**
* pix转dip
*/
fun Float.toDp():Float{
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,this,Resources.getSystem().displayMetrics)
}
fun main() {
val toDp = 12f.toDp()
print(toDp)
}
19.kotlin重的inline内联函数
例如Kotlin自带的repeat函数,就是使用的inline函数
使用场景:传入参数类型是函数类型的时候
好处是:
(1)会直接将inline函数的方法体,copy到调用的地方,然后再去编译生成字节码
(2)因为函数类型在调用时会生成一个对象,频繁调用会增大开销
示例:
/**
* @param sleepTimes 睡眠时间
*/
inline fun showTime(sleepTimes :()->Unit){
print("start${System.currentTimeMillis()}")
sleepTimes()
print("end${System.currentTimeMillis()}")
}
fun main() {
showTime {
print("不睡了,起来撸代码")
}
}
20.函数类型的声明使用
示例:
拿View的click事件为例,下面是Java方式
package com.zhboy.factoryaddemo
class View (){
interface OnClickListener{
fun onClick(view: View)
}
fun setOnClickListener(listener: OnClickListener){
}
}
fun main() {
val view = View()
view.setOnClickListener(object :View.OnClickListener{
override fun onClick(view: View) {
print("点击完毕")
}
})
}
下面是是kotlin中的方式,kotlin支持方法作为参数传入,Java不可以。
以下函数类型的声明的方式:
package com.zhboy.factoryaddemo
class View (){
fun setOnClickListener(listener:(View)->Unit){
}
}
fun main() {
val view = View()
view.setOnClickListener {
print("点击完毕")
}
}
扩展:上面这种方式在Java中调用会是用function接口的方式调用,如下:
class TestView {
public static void main(String[] args) {
new View().setOnClickListener(new Function1<View, Unit>() {
@Override
public Unit invoke(View view) {
return null;
}
});
}
}
21.by lazy的作用和使用场景
作用:
(1)被by lazy声明的对象只会生成一次
(2)该对象只有在被调用的时候,才会去创建
示例:
MainActivity
class MainActivity : AppCompatActivity(),BaseView<MainPresenter> {
override val presenter by lazy {
MainPresenter(this)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
presenter.userLogin("小明", "12233")
}
}
具体业务逻辑P层
package com.zhboy.factoryaddemo
/**
* @author: zhou_hao
* @date: 2020/11/26
* @description:业务逻辑P层
*/
class MainPresenter(activity:MainActivity) {
companion object{
private const val login_api = "/user/login"
}
fun userLogin(name:String,password:String){
print("调用接口去登录,用户名${name},密码${password}")
}
}
V层接口
package com.zhboy.factoryaddemo
/**
* @author: zhou_hao
* @date: 2020/11/26
* @description: V层接口
**/
interface BaseView<T>{
//抽奖变量,kotlin中有
val presenter:T
}
22.by 委托的使用
定义,顾名思义,将相同的操作委托给另一个对象来做
比如属性委托,以sp文件存储为例
示例:
package com.zhboy.factoryaddemo
import android.content.Context
import android.content.SharedPreferences
import androidx.core.content.SharedPreferencesCompat
import kotlin.properties.ReadOnlyProperty
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
/**
* @author: zhou_hao
* @date: 2020/11/26
* @description: By关键字的使用
*
**/
class SpSaver(private var key: String) : ReadWriteProperty<Nothing?, String> {
override fun getValue(thisRef: Nothing?, property: KProperty<*>): String {
return SpUtils.getValue(key)
}
override fun setValue(thisRef: Nothing?, property: KProperty<*>, value: String) {
SpUtils.setValue(key,value)
}
}
fun main() {
var username :String by SpSaver("name")
val password :String by SpSaver("password")
//赋值
username = "dfsdfdsf"
}
object SpUtils{
fun getValue(key: String):String{
//sp获取值
return ""
}
fun setValue(key: String,value:String){
//sp文件做存储
}
}
23.kotlin中的标准函数
会指定一个作用域,知识返回值不同
如果需要返回自身,就是用apply 或者 also
also 把调用对象当参数传入,可以改变对象
apply是调用对象的方法 ,不可以改变对象,只能改变对象方法
如果不需要返回自身,就是用let或者run
run一般用于,需要返回最后一行的场景
let一般用于做对象的非null处理
24.kotlin协程相关
协程是什么:它是Kotlin官方提供线程框架,其终极特点是非阻塞式挂起,可将不同线程的代码在同一个代码块中执行。
挂起函数是什么:挂起的是协程,在遇到suspend时就会挂起协程(其实就是切了个线程),任务执行完成后,会自动切回之前的线程,
为什么挂起函数必须在协程或者另一个挂起函数中调用:因为协程任务执行完成之后,需要切回之前的线程,协程才能切换线程。
线程和协程的关系: 协程就是基于线程的上层框架
什么是非阻塞:阻塞实际上就是耗时等待,耗时分为两种
(1)cpu计算耗时
(2)I/O的耗时
非阻塞就是不等待
真香:让我们轻松的写出复杂的并发代码,爽的一批。
示例:
launch(Dispatchers.Main) {//主线程
val loginInfo = Api.login()//网络请求 后台线程
usernameTv.text = loginInfo.userName//更新UI 主线程
}
推荐看这位大神讲的关于协程的东西:
https://www.bilibili.com/video/BV1JE411R7hp/?spm_id_from=333.788.videocard.0