MVVM + kotlin+ jetpack

3.遥遥领先 Android kotlin 项目中超高频用法

2024-03-31  本文已影响0人  鹏城十八少
目录:
1. 变量的原理, 变量和属性
2. 基础数据结构, 数组, 集合,字符串相关
3. 函数
4. 异常
5. 循环
6. this语法
7. 类型转换

1. 变量类型: 变量和属性

1.1 在编译之后会变成包装类型, 比如

kolin数组, 为啥不用java的, 而是多弄一套, 因为kotlin里面的更牛逼, 并且它最后生产的是包装类型

1.2 属性原理:get方法私有化

自动生成get和set方法
生成get和set方法,不能自动生成

package kk.yuedong.com.myapplication

class TestBean {


    private var height = 0

    private var weight = 0


    fun getHeight(): Int {
        return height
    }

    fun setHeight(height: Int) {

        this.height = height;
    }
}
在Kotlin中,getter和setter是可选的,如果你没有在代码中创建它们,它是会默认自动生成,是看不到的:

class Account {
    var name: String = ""
    var age: Int = 0
    var balance: Double = 0.0
}
以上的代码,就算不写getter/setter,默认也会生成getter和setter,例如:

class Account {
    var name: String = ""
    var age: Int = 0
    var balance: Double = 0.0

    // 这种set和get方法不推荐在代码中自己手动去写
        set(vaule){
            field = value
        }
        get() = field
}

1.3.常量 const

只能修饰基本的数据类型, 不能修饰类!

private const val AI_COACH_VIDEO_INFO = "ai_coach_video_info"
ch.setPivotY(svv_coach.height.toFloat())

Boolean类型,如果不执行,那么就不一定返回boolean

if(result!=null&&result.ok()){
    initSdk(isUseYuedongSdk)
}else{
    ToastUtil.showShort("模型加载失败,请重试")
    finish()
}

从一个方法传到另外一个方法默认是final。和java不一样,就像内部类

var url=modelInfo?.model_file_url
if (url != null&&vesion != null&&name != null) {
    download(url,videoId,vesion ,name,true)
    download(url,videoId,vesion ,name,false)
};
fun download(url: String, videoId: Int, version: String, name: String,isModelNotPro:Boolean){
    var path=AndroidRComp.getPrivateDir("aiModel")
    var dirPath=path+File.separator+videoId

    val dirFile = File(dirPath);
    if(!dirFile.exists()){
        dirFile.mkdirs()
    }
    var urlTemp=""
    var fileName= version + "_" + name+version
    if(isModelNotPro){
        fileName=fileName+".tnnmodel"
        urlTemp=url+"model"
2. 基础数据结构, 数组, 集合,字符串相关

在Kotlin中,associate 是一个常用于 Map 创建的函数,它可以将一个集合中的元素转换成键值对的形式,从而构建一个新的映射(Map)。

2.1 数组的扩展函数

  1. . associate 函数有几种不同的形式,最常见的是 associateWith 和 associateBy。
    2). distinctby 去重用的
data class Person(val name: String, val age: Int)  
  
fun main() {  
    val people = listOf(  
        Person("Alice", 25),  
        Person("Bob", 30),  
        Person("Alice", 25), // 与第一个 Alice 重复  
        Person("Charlie", 35)  
    )  
  
    // 根据名字去重  
    val distinctPeopleByName = people.distinctBy { it.name }  
  
    println(distinctPeopleByName)  
    // 输出可能是: [Person(name=Alice, age=25), Person(name=Bob, age=30), Person(name=Charlie, age=35)]  
    // 注意:这里不一定输出第一个 Alice,因为 distinctBy 不保证顺序  
}

2.2 集合。可变集合和不可变集合:

集合用法
首先声明如下 IntArray 和 List:

🏝️
val intArray = intArrayOf(1, 2, 3)
val strList = listOf("a", "b", "c")
var reportList: MutableList<CourseReportBean>?=null
val titles = arrayOf(getString(R.string.upload), getString(R.string.download))

2.2.1) list扩展函数:

1).filter:过滤集合中满足条件的元素
2).fold
3).any
4).all
5).find
6).forEach

2.2.2).Map扩展函数:

flatMap
mapValues
filterKeys
sequences: 性能优化, 避免创建中间的集合
在 Kotlin 中,Sequence 是一个表示元素序列的接口,它提供了一种惰性(lazy)的方式来处理集合数据。与 List、Set 和 Map 等集合类型不同,Sequence 不会在创建时立即计算所有元素,而是在每次迭代时按需计算。这使得 Sequence 在处理大量数据或无限序列时特别有用,因为它可以显著减少内存消耗并提高性能

2.3. 字符串String的操作

字符串模板$:

fun main(args: Array<String>) {
    val s = "runoob"
    val str = "$s.length is ${s.length}" // 求值结果为 "runoob.length is 6"
    println(str)
}

toString生成,$符号

override fun toString(): String {
    return "TestBean(height=$height, weight=$weight)"
}

Kotlin 为我们提供了一种更加方便的写法:

🏝️
val name = "world"
//         👇 用 '$' 符号加参数的方式
println("Hi $name")

比如打印:

YDLog.logDebegV2(TAG, "recognizeSuc $reRecognize")

Kotlin的构造函数直接声明在类的后面,并且变量的声明也可以在函数的参数中声明,最后字符串的输出,直接使用${变量名}的形式输出

var testBean=TestBean();
var height=testBean.getHeight();
Log.d("peng","height="+height);
println("$height start paly")
1). 拼接

使用 joinToString 函数

val items = listOf("apple", "banana", "cherry")  
val joined = items.joinToString(", ") // 结果为 "apple, banana, cherry"
2). 比较.

使用 == 运算符进行引用比较

val str1 = "hello"  
val str2 = "hello"  
val str3 = str1 + "" // 虽然是相同的内容,但是通过拼接创建的  
  
println(str1 == str2) // 输出 true,因为 str1 和 str2 引用的是同一个对象  
println(str1 == str3) // 输出 false,因为 str3 是通过拼接创建的,与 str1 和 str2 引用不同

属性

val message = "The number is ${number * 2}." // 结果为 "The number is 246."

3. 函数:

3.1 单表达式函数:

当函数返回单个表达式时,可以省略花括号
例如:

fun sum(x: Int, y: Int): Int {
    return x + y
}

等价于:

fun sum(x: Int, y: Int): Int = x + y

等价于: (原理: 自己都不知道返回的类型, 可以通过kotlin的类型推导)

//编译器可以推断出该函数的返回类型
fun sum(x: Int, y: Int) = x + y

在Kotlin中,if是表达式,而不是语句。语句和表达式的区别在于,表达式有值,能作为另一个表达式的一部分使用;语句总是包围着它的代码块中的顶层元素,并且没有自己的值。
如果函数体写在花括号中,称这个函数有代码块体。如果它直接返回一个表达式,称有表达式体,如下

fun max(a: Int, b: Int): Int = if (a > b) a else b

3.2 中缀函数

要创建一个中缀函数,您需要按照以下步骤进行:

• 将函数定义为成员函数或扩展函数。
• 在 fun 关键字之前添加 infix 关键字。
下面是定义中缀函数的一般语法:

infix fun <ReceiverType>.functionName(param: ParamType): ReturnType {
    // 函数逻辑在这里
    // ...
    return result
}

中锥函数的具体使用案例:
定义中缀函数: 要定义中缀函数,需要使用 infix 关键字将函数标记为中缀,并将其定义为成员函数或扩展函数

infix fun Int.add(x: Int): Int {
    return this + x
}

调用中缀函数: 调用中缀函数时,可以省略点符号,直接使用函数名和参数,如下所示:

//这里的 add 就是一个中缀函数。
// 等同于 5.add(3)
val result = 5 add 3 

3.3 本地函数(嵌套函数)

首先来看下这段代码,这是一个简单的登录的函数:

fun login(user: String, password: String, illegalStr: String) {
    // 验证 user 是否为空
    if (user.isEmpty()) {
        throw IllegalArgumentException(illegalStr)
    }
    // 验证 password 是否为空
    if (password.isEmpty()) {
        throw IllegalArgumentException(illegalStr)
    }
}

该函数中,检查参数这个部分有些冗余,我们又不想将这段逻辑作为一个单独的函数对外暴露。这时可以使用嵌套函数,在 login 函数内部声明一个函数:

🏝️
fun login(user: String, password: String, illegalStr: String) {
           👇 
    fun validate(value: String, illegalStr: String) {
      if (value.isEmpty()) {
          throw IllegalArgumentException(illegalStr)
      }
    }
   👇
    validate(user, illegalStr)
    validate(password, illegalStr)
}

4. 异常

Nothing: 用于方法抛出异常
方法永远不返回, 而是抛出一个异常
在 Kotlin 中,Nothing 是一个特殊的类型,它表示一个永远不会有实例的类型。换句话说,Nothing 是所有类型的子类型,但没有类型是其超类型(除了 Nullable<Nothing>)。你可以将 Nothing 看作是一个空的类型,它没有实际的实例。

Nothing 类型主要用于以下几种情况:

表示永远不会返回的函数:如果一个函数声明其返回类型为 Nothing,那么这意味着该函数永远不会正常返回。这样的函数通常用于抛出异常或执行其他形式的程序终止。

fun fail(): Nothing {  
    throw IllegalStateException("This function always fails")  
}
val isSuccess: Boolean
    get() = errorCode == 0

5.区间:用于for循环

循环遍历:
linklistTasks.forEachIndexed{ index, item ->
    itemList.add(item)
}

for循环的写法
有步长
区间表达式由具有操作符形式 .. 的 rangeTo 函数辅以 in 和 !in 形成。

区间是为任何可比较类型定义的,但对于整型原生类型,它有一个优化的实现。以下是使用区间的一些示例:

    var recyclerView=findViewById<RecyclerView>(R.id.recycler_view);

    recyclerView.layoutManager = LinearLayoutManager(this)
    var adapter=MyAdapter(this,initData()!!);

    recyclerView.adapter=adapter;

}

private fun initData(): ArrayList<String>? {
    var list=ArrayList<String>()
    for (i in 0..50){
        list.add(""+i);
    }
    Log.d("tag","list.size------"+ list.size)
    return list
}
6. this语法:
progressDialog = ProgressDialog.show(this@AICoachSingleTrainActivity,

7. 类型转换

7.1) 在Kotlin中如何将String转换为Int?

在Kotlin中可使用toInt()方法将字符串值转换为整数或INT。 以下是示例用法:

数据格式转换

this.sendEmptyMessageDelayed(MSG_TIMER, TIME_INTERVAL.toLong())

7. 2).自动类型转换

//函数返回值类型可以是动态的:自动类型转换
fun add2(num :Int,num2:Int)=num+num2

Kotlin 可以编译成Java字节码,也可以编译成 JavaScript,方便在没有 JVM 的设备上运行。
public fun sum(a: Int, b: Int): Int = a + b // public 方法则必须明确写出返回类型

7.3 )可变长参数函数:和asyncTask的一样

函数的变长参数可以用 vararg 关键字进行标识:

fun vars(vararg v:Int){
    for(vt in v){
        print(vt)
    }
}

// 测试
fun main(args: Array<String>) {
    vars(1,2,3,4,5)  // 输出12345

类型检测及自动类型转换我们可以使用 is 运算符检测一个表达式是否某类型的一个实例(类似于Java中的instanceof关键字)。
is 是关键字
‘is’表示你可以这样使用关键字
if (type is ParameterizedType) {

fun getStringLength(obj: Any): Int? {
  if (obj is String) {
    // 做过类型判断以后,obj会被系统自动转换为String类型
    return obj.length 
  }

  //在这里还有一种方法,与Java中instanceof不同,使用!is
  // if (obj !is String){
  //   // XXX
  // }

  // 这里的obj仍然是Any类型的引用
  return null
}

7.4 ) 比较两个数字

Kotlin 中没有基础数据类型,只有封装的数字类型,你每定义的一个变量,其实 Kotlin 帮你封装了一个对象,这样可以保证不会出现空指针。数字类型也一样,所以在比较两个数字的时候,就有比较数据大小和比较两个对象是否相同的区别了。

在 Kotlin 中,三个等号 === 表示比较对象地址,两个 == 表示比较两个值大小。

fun main(args: Array<String>) {
    val a: Int = 10000
    println(a === a) // true,值相等,对象地址相等

    //经过了装箱,创建了两个不同的对象
    val boxedA: Int? = a
    val anotherBoxedA: Int? = a

    //虽然经过了装箱,但是值是相等的,都是10000
    println(boxedA === anotherBoxedA) //  false,值相等,对象地址不一样
    println(boxedA == anotherBoxedA) // true,值相等
}

链式调用(类似Glide的模式)

Glide.with(context)
.load(url)
.error(icon)
.into(view);

如果接口只有一个,就可以用lameda。如果有2个的话,就要用object

var completeListener=MediaPlayer.OnCompletionListener {

    YDLog.logError(TAG, "OnCompletionListener:", "OnCompletionListener:")
    var curCompleteTime=System.currentTimeMillis()
    if(curCompleteTime-lastCompleteTime>2000){
        mPresenter.stopRecognize()
    }
    lastCompleteTime=System.currentTimeMillis()
}

 var downloadListener=object :ScalableVideoViewAsyn.DownLoadListener{

    override fun ProgressChanged(netFile: NetFile?, progress: Int) {
       
    }

    override fun DownloadFinished(netFile: NetFile?, result: NetResult?) {

    }
}

).设置监听和回调

var lister = object : OnTabSelectedListener {
    override fun onTabReselected(tab: TabLayout.Tab?) {

    }

    override fun onTabSelected(tab: TabLayout.Tab?) {
        binding.viewpager.currentItem = tab!!.position
        tab?.customView?.findViewById<TextView>(R.id.tv_title)
            ?.setTextColor(getColor(R.color.color_08C5AC))
        tab?.customView?.findViewById<View>(R.id.indicator)
            ?.setBackgroundColor(getColor(R.color.color_08C5AC))
    }

    override fun onTabUnselected(tab: TabLayout.Tab?) {
        tab?.customView?.findViewById<TextView>(R.id.tv_title)
            ?.setTextColor(getColor(R.color.color_7A7A7A))
        tab!!.customView?.findViewById<View>(R.id.indicator)
            ?.setBackgroundColor(getColor(R.color.color_transparent))
    }
}
有参数的类的写法
binding.viewpager.adapter = object : FragmentStatePagerAdapter(
    supportFragmentManager,
    FragmentStatePagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT
) {

    override fun getCount(): Int {
        return fragments.size
    }

    override fun getItem(position: Int): Fragment {
        return fragments[position]
    }

    override fun getPageTitle(position: Int): CharSequence? {
        return titles[position]
    }
}

上一篇 下一篇

猜你喜欢

热点阅读