关于kotlin:Android-Kotlin语言学习第一课基本知识

52次阅读

共计 8860 个字符,预计需要花费 23 分钟才能阅读完成。

Android Kotlin 语言学习第一课:基本知识

一:Kotlin 的类的定义
(1)如果一个类容许被继承必须应用 open 关键字润饰

(2)抽象类默认是 open 润饰
抽象类简介 : 抽象类不能被实例化 , 在 class 关键字前应用 abstract 润饰 ;
抽象类 , 默认应用 open 关键字润饰 , 能够间接继承 ;
形象办法 , 默认应用 open 关键字润饰 , 能够间接 override 重写 ;

抽象类总结 :
① 申明 : 抽象类中应用 abstract 申明 ;
② 成员 : 抽象类中既能够定义失常属性和办法 , 又能够定义形象的属性和办法 ;
③ 继承 : 抽象类能够继承抽象类 , 抽象类也能够继承失常类 , 失常类能够继承抽象类 ;
④ 重写 : 抽象类中能够应用形象办法重写失常办法 , 也能够进行失常的办法重写 ;
⑤ 特色 : 形象办法只能定义在抽象类中 , 失常类中不能有形象办法 ;

/**
 * @author zhiqiangRuan
 * @ClassName
 * @Date  2022/6/8
 */
abstract class BaseActivity : AppCompatActivity() {
    /**
     * kotlin 容许一个类继承另一个类
     * kotlin 所有的类都继承自 Any 类(Any 不是 java.lang.Object)* Any 类是所有类的超类,对于没有超类型申明的类是默认超类
     * Kotlin 规定一个类能够给继承,必须应用 open 关键字润饰
     * */

    /**
     * 抽象类:关键字为 abstract
     * 形象函数:abstract fun initView()
     * 形象属性:abstract var name:String */

    /**
     * 变量能够定义为可变 (var) 和不可变(val)* 常量定义:val 相当于被 final 润饰  var 相当于可变非 final 润饰
     * 等价于 Java:public static final String TAG=BaseActivity.class.getSimpleName()*/
    // 定义标记
    val TAG: String = this.javaClass.simpleName

    // 初始化布局 View
    abstract fun initView()

    // 初始化数据
    abstract fun initData()

    // 初始化获取布局 id, 带返回值的形象办法
    abstract fun getLayoutId(): Int

    /**
     * 语法定义
     * fun 办法名(参数名:参数类型):返回值类型{
     *
     * return 返回值
     *
     * }
     *
     * 无返回值能够应用 Unit 代替返回值类型 ? 代表可空
     * Kotlin 是 null 平安的语言 Byte ,Short,Int ,Long 型的变量都是不能承受 null 值,如果要存储 null 值须要应用 Byte?,Short?,Int?,Long?
     *
     *  override fun onCreate(savedInstanceState: Bundle?):Unit{
     *
     *  }
     **/
    override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)
        setContentView(getLayoutId())
        initView()
        initData()}

    override fun onDestroy() {super.onDestroy()
    }
}

二:变量和函数
val(value 的简写) 用来申明一个不可变的变量,这种变量在初始赋值之后就再也不能从新赋值,对应 Java 中的 final 变量;
var(variable 的简写)用来申明一个可变的变量,这种变量在初始赋值会后依然能够再被从新赋值,对应 Java 中的非 final 变量;

//ps:Kotlin 每一行代码的结尾是不必加分号的。fun main(){
    val a = 10
    val isFailed: Boolean get() = i > 3// 赋值操作, i 为变量;
    println("a ="+ a)
}

Kotlin 的类型推导机制: 代码中应用 val 关键字定义了一个变量 a, 并将它赋值为 10,这里 a 就会被主动推导成整型变量。
因为既然你要把一个整数赋值给 a, 那么 a 就只能是整型变量,而如果你要把一个字符串赋值给 a,那么 a 就会被主动推导成字符串变量;

fun (function 的简称)是定义函数的关键字,无论定义什么函数,都肯定要是用 fun 来申明;
fun 办法体(参数 1:参数类型,参数 2:参数类型):返回值类型{
return 返回值
}

 fun largerNumber(num1:Int,num2: Int):Int{return max(num1,num2)
    }
// 等价于
fun largerNumber(num1:Int,num2: Int)=max(num1,num2)
 // 这种是更简便写法,Kotlin 的推导机制   

三:kotlin-android-extensions 插件援用报错问题
其实在 Kotlin 1.4.20 中,JetBrains 废除了 kotlin-android-extensions 编译插件,转而倡议咱们应用 ViewBinding


四:Kotlin TODO 编译闪退问题

 override fun initData() {TODO("Not yet implemented")
    }
/**
 * @author zhiqiangRuan
 * @ClassName
 * @Date  2022/6/8
 */
class FirstActivity : BaseActivity(), View.OnClickListener {
override val TAG:String=this.javaClass.simpleName
    //kotlin 中容许所有的类都继承
/**
     *  lateinit 关键字
     * 提早初始化
     * 这个关键字通知编译器,我无奈申明的时候就初始化,然而我保障我在应用前肯定会初始化,你就别给我查看了。*/
     * /** 咱们应用非空定义会报错,无奈申明时候就晓得这个 view 是什么,应用空定义能够定义 */
     //var tvTitle:TextView?=null
    lateinit var tvTitle:TextView

    override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)
    }

    override fun initView() {
        /**
         * 第一种写法:* findViewById 写法,在泛型中指定该控件类型
         *
         * 第二种写法: 去掉泛型在后面申明改控件的类型
         * var tvTitle :TextView=findViewById(R.id.tv_title)
         *
         * 第三种不要 findViewById 的形式
         * 第一步:在 dependencies 中 classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version" 插件
         * 第二步:build.gradle(app 下的)的 dependencies 中增加
         * implementation "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
         * 第三步:* build.gradle(app 下的)的 plugins 中增加 id 'kotlin-android-extensions'
         * 第四步:* 同步一下
         *
         *  tv_title.text="aaa" 间接就赋值了
         * 其实在 Kotlin 1.4.20 中,JetBrains 废除了 kotlin-android-extensions 编译插件,转而倡议咱们应用 ViewBinding
         *  Warning: The 'kotlin-android-extensions' Gradle plugin is deprecated. Please use this migration guide (https://goo.gle/kotlin-android-extensions-deprecation) to start working with View Binding (https://developer.android.com/topic/libraries/view-binding) and the 'kotlin-parcelize' plugin.
         * */

      tvTitle = findViewById<TextView>(R.id.tv_title)
tvTitle.setOnClickListener(this)
    }

    override fun initData() {}


    override fun getLayoutId(): Int {return R.layout.activity_first}

    fun largerNumber(num1:Int,num2: Int):Int{return max(num1,num2)
    }
override fun onClick(v: View?) {when (v?.id) {
            R.id.tv_title -> {Log.d(TAG,"我点击了")
            }
        }
    }

}

五:Kotlin findViewById 是想给布局赋值,给一个 textView 设置文字
在理论的业务场景中,View 永远不会为空,因为一个为空的 View 是没有意义的,然而,咱们却申明了一个能够为空的 View,这样一看起来比拟矛盾,二会影响浏览性。

/**
     *  lateinit 关键字
     * 提早初始化
     * 这个关键字通知编译器,我无奈申明的时候就初始化,然而我保障我在应用前肯定会初始化,你就别给我查看了。*/
    /** 在理论的业务场景中,View 永远不会为空,因为一个为空的 View 是没有意义的,然而,咱们却申明了一个能够为空的 View,这样一看起来比拟矛盾,二会影响浏览性。*/
    /** 咱们应用非空定义会报错,无奈申明时候就晓得这个 view 是什么,应用空定义能够定义 */
//    lateinit var tvTitle:TextView
    var tvTitle:TextView?=null

六:OnClickListener 监听
extends 被 : 代替,implement 被 , 代替

class MainActivity : AppCompatActivity() {
    // 提早初始化
    lateinit var tvClick: TextView
    override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        tvClick = findViewById<TextView>(R.id.tv_click)

        tvClick.setOnClickListener(object : View.OnClickListener {override fun onClick(v: View?) {
                // 点击事件监听
                // 获取 Intent 对象
                val intent = Intent()
                // 获取 class 是应用:: 反射(那么问题来了, 反射是个什么鬼? 小白的悲痛啊, 连忙钻研钻研去
                intent.setClass(this@MainActivity, FirstActivity::class.java)
                startActivity(intent)

            }

        })


    }
}

第二种形式:

/**
 * @author zhiqiangRuan
 * @ClassName
 * @Date  2022/6/8
 */
class FirstActivity : BaseActivity(), View.OnClickListener {
    override val TAG: String = this.javaClass.simpleName
    //kotlin 中容许所有的类都继承
    /**
     *  lateinit 关键字
     * 提早初始化
     * 这个关键字通知编译器,我无奈申明的时候就初始化,然而我保障我在应用前肯定会初始化,你就别给我查看了。*/
    /** 在理论的业务场景中,View 永远不会为空,因为一个为空的 View 是没有意义的,然而,咱们却申明了一个能够为空的 View,这样一看起来比拟矛盾,二会影响浏览性。*/
    /** 咱们应用非空定义会报错,无奈申明时候就晓得这个 view 是什么,应用空定义能够定义 */
    lateinit var tvTitle: TextView
    lateinit var tvRecycler: RecyclerView

    //    var tvTitle: TextView? = null
    private var myAdapter: MyAdapter? = null
    // 初始化数据汇合
    private var students= ArrayList<Student>()

    override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)
    }

    override fun initView() {
        /**
         * 第一种写法:* findViewById 写法,在泛型中指定该控件类型
         *
         * 第二种写法: 去掉泛型在后面申明改控件的类型
         * var tvTitle :TextView=findViewById(R.id.tv_title)
         *
         * 第三种不要 findViewById 的形式
         * 第一步:在 dependencies 中 classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version" 插件
         * 第二步:build.gradle(app 下的)的 dependencies 中增加
         * implementation "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
         * 第三步:* build.gradle(app 下的)的 plugins 中增加 id 'kotlin-android-extensions'
         * 第四步:* 同步一下
         *
         *  tv_title.text="aaa" 间接就赋值了
         * 其实在 Kotlin 1.4.20 中,JetBrains 废除了 kotlin-android-extensions 编译插件,转而倡议咱们应用 ViewBinding
         *  Warning: The 'kotlin-android-extensions' Gradle plugin is deprecated. Please use this migration guide (https://goo.gle/kotlin-android-extensions-deprecation) to start working with View Binding (https://developer.android.com/topic/libraries/view-binding) and the 'kotlin-parcelize' plugin.
         * */

        tvTitle = findViewById<TextView>(R.id.tv_title)
        tvRecycler = findViewById<RecyclerView>(R.id.tv_recycler)
        // 设置布局排列形式
        val linearLayoutManager = LinearLayoutManager(this)
        linearLayoutManager.orientation = LinearLayoutManager.VERTICAL
        tvRecycler.layoutManager = linearLayoutManager
        // 增加分割线
        tvRecycler.addItemDecoration(DividerItemDecoration(this, LinearLayoutManager.VERTICAL))
        // 加载适配器
        myAdapter = MyAdapter(students)
        // 设置适配器
        tvRecycler.adapter = myAdapter
        tvTitle.setOnClickListener(this)
    }

    override fun initData() {for (i in 0 until 50) {val student=Student()
            student.name=i.toString()+"同学"
            student.age=i
            students.add(student)
        }
    }


    override fun getLayoutId(): Int {return R.layout.activity_first}

    fun largerNumber(num1: Int, num2: Int): Int {return max(num1, num2)
    }

    override fun onClick(v: View?) {when (v?.id) {
            R.id.tv_title -> {Log.d(TAG, "我点击了")
            }
        }
    }

}

七:kotlin 之构造函数(constructor)

java 中的构造函数是与类名雷同即可,kotlin 外面的构造函数是用 constructor 关键字示意。
kotlin 外面的构造函数分为主构造函数和次构造函数。主构造函数只能有一个,次构造函数个数不限度,能够有一个或者多个

// 主构造方法如下,跟在类名前面
class Person constructor(name:String){ }

class Person constructor(){}
// 当主构造方法没有任何注解或者可见性修饰符时,能够省略,写成上面这样
class Person { }

// 这种就是有注解标记的主构造方法,不能省略
class Person @Inject internal constructor(){}

// 次构造方法,一个无参的次构造方法,一个有一个参数的次构造方法

class Person {constructor(){ }
    
    constructor(name:String){}}

八:Kotlin 适配器编写和数据 bean

/**
 * @author zhiqiangRuan
 * @ClassName
 * @Date  2022/6/9
 */
/**
 * MyAdapter (val students:List<Student>)
 * 是一个主构造函数
 * List<Student> 参数类型 */
class MyAdapter(val students: List<Student>) : RecyclerView.Adapter<MyAdapter.MyViewHolder>() {

    /**
     * inner 定义外部类
     *
     * class MyViewHolder(view: View)
     * 主构造函数 View
     * 次构造函数 constructor
     * */
    inner class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) {val tvName: TextView = view.findViewById(R.id.tv_name)
        val tvAge: TextView = view.findViewById(R.id.tv_age)

    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {val view = LayoutInflater.from(parent.context).inflate(R.layout.first_item, parent, false)
        return MyViewHolder(view)
    }

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {val student = students[position]
        holder.tvName.text = student.name
        holder.tvAge.text = student.age.toString()}

    override fun getItemCount(): Int {return students.size}
}

布局文件 first_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/tv_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:text="姓名" />
        <TextView
            android:id="@+id/tv_age"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:text="年纪" />
    </RelativeLayout>

</LinearLayout>

Student 数据 bean

/**
 * @author zhiqiangRuan
 * @ClassName
 * @Date  2022/6/9
 */
class Student : Serializable {
    var name: String? = null
    var age: Int? = 0

}

END: 新常识学习会面对很多的坑,但也会发现很多美好

正文完
 0