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:新知识学习会面对很多的坑,但也会发现很多美妙
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。