Kotlin初体验
距离kotlin成为Android一级开发语言已经一年了,这节将从零开始,实现kotlin的几个小知识点。 以下操作是在AndroidStudio3.0.1下完成的,如果是3.0以下版本的AndroidStudio,需要安装好kotlin插件才能使用Kotlin进行开发 Kotlin教程推荐 官网文档,黑马教程,《Kotlin for android developers》中文版翻译 相关代码已经上传到Github的KotlinPractice文件夹下了 创建项目: 在创建项目中勾选kolin支持后直接下一步即可 勾选kotlin支持 创建完项目后我们发现主类已经是使用了kotlin代码了,我们去project的build.gradle目录下可以看到 ext.kotlin_version = '1.1.51' kotlin //版本号 dependencies { classpath 'com.android.tools.build:gradle:3.0.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"//依赖 } 以及module下build.gradle的: apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' 实际上这就是我们刚才勾选kotlin后给我们自动生成的,如果我们想要在现有Java代码项目中使用kotlin,那么我们就需要手动的去添加这些依赖,或者使用方便的java代码转kotlin来进行配置,我们看到MainActivity默认已经是kotlin类了 /** * : AppCompatActivity() * :类名,表示继承于AppCompatActivity类 */ class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } } 为TextView控件赋值: 我们在布局从添加一个TextView,id命名为text_01 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.administrator.kotlin.MainActivity"> <TextView android:id="@+id/txt_01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="测试文本" /> </LinearLayout> 回到Activity,在activity的导包中添加这一行 import kotlinx.android.synthetic.main.activity_main.* 它的作用现在只要知道添加了这一行后我们就不需要再findViewById就可以了,activity_main的意思是Activity布局的包名。 import kotlinx.android.synthetic.main.activity_main.* /** * : AppCompatActivity() :类名,表示继承与什么类 */ class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 为TextView设置值,koltin的语句后面是不需要;的,但是如果你加上也不会报错的 txt_01.setText("你好,世界") } } 运行程序,确实和我们想要的是一样的 设置按钮点击事件 我们再为布局添加3个button按钮 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.example.administrator.kotlin.MainActivity"> <TextView android:id="@+id/txt_01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="测试文本" /> <Button android:id="@+id/btn_01" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="按钮1" /> <Button android:id="@+id/btn_02" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="按钮2" /> <Button android:id="@+id/btn_03" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="按钮3" /> </LinearLayout> 回到Activity,让MainActivity类继承于View.OnClickListener接口,我们可以看到koltin继承接口是使用,号进行的,如果我们想要继承多个接口,只需要使用多个,分隔开来就行了 /** * : AppCompatActivity() :类名,表示继承于什么类 * ,View.OnClickListener, View.OnLongClickListener 表示继承于 View.OnClickListener 点击事件接口, View.OnLongClickListener 长按事件接口 */ class MainActivity : AppCompatActivity(), View.OnClickListener, View.OnLongClickListener { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 为TextView设置值,koltin的语句后面是不需要;的,但是如果你加上也不会报错的 txt_01.setText("你好,世界") } /** * 重写OnClickListener接口的onClick方法 */ override fun onClick(p0: View?) { } /** * 重写OnLongClickListener接口的onLongClick方法 */ override fun onLongClick(p0: View?): Boolean { return false } } 然后就是我们熟悉的在点击事件里面使用switch找到对应控件的id了,只是在kotlin里面是使用when /** * 重写OnClickListener接口的onClick方法 */ override fun onClick(p0: View?) { when (p0!!.id) { R.id.btn_01 -> { Toast.makeText(this, "按钮1", Toast.LENGTH_LONG).show() } R.id.btn_02 -> { Toast.makeText(this, "按钮2", Toast.LENGTH_LONG).show() } R.id.btn_03 -> { Toast.makeText(this, "按钮3", Toast.LENGTH_LONG).show() } } } 最后要注意,虽然我们通过import kotlinx.android.synthetic.main.activity_main.*使得不需要写控件的fndId,但是我们仍然是要写setOnClickListener(this)控件点击回调监听的 完整代码: import android.support.v7.app.AppCompatActivity import android.os.Bundle import android.view.View import android.widget.Toast import kotlinx.android.synthetic.main.activity_main.* /** * : AppCompatActivity() :类名,表示继承与什么类 */ class MainActivity : AppCompatActivity(), View.OnClickListener, View.OnLongClickListener { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 为TextView设置值,koltin的语句后面是不需要;的,但是如果你加上也不会报错的 txt_01.setText("你好,世界") // 设置控件的回调监听 init() } /** * 设置控件的回调监听 */ private fun init() { btn_01.setOnClickListener(this) btn_02.setOnClickListener(this) btn_03.setOnClickListener(this) } /** * 重写OnClickListener接口的onClick方法 */ override fun onClick(p0: View?) { when (p0!!.id) { R.id.btn_01 -> { Toast.makeText(this, "按钮1", Toast.LENGTH_LONG).show() } R.id.btn_02 -> { Toast.makeText(this, "按钮2", Toast.LENGTH_LONG).show() } R.id.btn_03 -> { Toast.makeText(this, "按钮3", Toast.LENGTH_LONG).show() } } } /** * 重写OnLongClickListener接口的onLongClick方法 */ override fun onLongClick(p0: View?): Boolean { return false } } 运行程序点击按钮后,出现了我们想要的吐司 实现网络请求 开始之前我们先在module下配置anko依赖,这是为了等下线程调度用的 module: dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation"org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" implementation 'com.android.support:appcompat-v7:26.1.0' implementation 'com.android.support.constraint:constraint-layout:1.1.0' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.1' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' // kotlin插件anko implementation "org.jetbrains.anko:anko-common:0.10.4" } 然后实现我们的network()请求网络方法,最后不要忘了在AndroidManifest.xml下添加网络权限 <uses-permission android:name="android.permission.INTERNET" /> /** * 重写OnClickListener接口的onClick方法 */ override fun onClick(p0: View?) { when (p0!!.id) { R.id.btn_01 -> { // 只进行网络请求 network(); } R.id.btn_02 -> { // 进行网路请求,并且进行json数据解析 Toast.makeText(this, "按钮2", Toast.LENGTH_LONG).show() } R.id.btn_03 -> { Toast.makeText(this, "按钮3", Toast.LENGTH_LONG).show() } } } /** * 网络请求 */ private fun network() { // 声明要请求的网址,在kotlin中,var能声明一切类型,而后面的:String其实是可以不加的 var string: String = "http://www.wanandroid.com/tools/mockapi/2872/k1" // 作用类似java在子线程中进行网络请求,但是async在kotlin中叫做协程 async() { val fore = URL(string).readText() Log.d("tonjies", fore) } } 观察日志,我们可以看到确实已经获取了Json数据 这里写图片描述 Json数据解析 接下来我们进行json数据的解析,首先添加gson解析依赖 // goso解析 compile "com.google.code.gson:gson:2.4" 我们创建bean实体类包,在包下创建解析实体类Student,我们不需要像Java那样去生成get和set对象,因为这kotlin已经帮我们生成好啦! /** * Created by 舍长 on 2018/4/28. * 描述: 数据请求实体类 */ class Student { var name:String?=null var age:String?=null } 在按钮2的点击事件里面写一个gson方法,在gson方法里将网络请求到的数据转换成实体类,并且回到UI线程,显示在文字控件上 /** * 重写OnClickListener接口的onClick方法 */ override fun onClick(p0: View?) { when (p0!!.id) { R.id.btn_01 -> { // 只进行网络请求 network(); } R.id.btn_02 -> { // 进行网路请求,并且进行json数据解析 Toast.makeText(this, "按钮2", Toast.LENGTH_LONG).show() gson(); } R.id.btn_03 -> { Toast.makeText(this, "按钮3", Toast.LENGTH_LONG).show() } } } /** * 网络请求并使用gson解析数据 */ private fun gson() { // 声明要请求的网址,在kotlin中,var能声明一切类型,而后面的:String其实是可以不加的 var string: String = "http://www.wanandroid.com/tools/mockapi/2872/student" // 作用类似java在子线程中进行网络请求,但是async在kotlin中叫做协程 async() { val fore = URL(string).readText() var fromJson: Student = Gson().fromJson(fore, Student::class.java) // 回到UI线程中去更新数据,这里的${属性名}是字符串模板,作用于Java的+属性名+相同 uiThread { txt_01.setText("学生的名字是${fromJson.name},年龄是${fromJson.age}") } } } 运行程序,点击按钮二,可以看到文字确实变成了我们想要的json数据:学习的名字是tonjies,年龄是18 这一小节的完整代码: 布局文件activity_main: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.example.administrator.kotlin.MainActivity"> <TextView android:id="@+id/txt_01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="测试文本" /> <Button android:id="@+id/btn_01" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="按钮1" /> <Button android:id="@+id/btn_02" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="按钮2" /> <Button android:id="@+id/btn_03" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="按钮3" /> </LinearLayout> MainActivity package com.example.administrator.kotlin import android.icu.lang.UCharacter.GraphemeClusterBreak.L import android.support.v7.app.AppCompatActivity import android.os.Bundle import android.util.Log import android.view.View import android.widget.Toast import com.example.administrator.kotlin.R.id.async import com.example.administrator.kotlin.bean.Student import com.google.gson.Gson import kotlinx.android.synthetic.main.activity_main.* import java.net.URL import org.jetbrains.anko.custom.async import org.jetbrains.anko.uiThread /** * : AppCompatActivity() :类名,表示继承与什么类 */ class MainActivity : AppCompatActivity(), View.OnClickListener, View.OnLongClickListener { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 为TextView设置值,koltin的语句后面是不需要;的,但是如果你加上也不会报错的 txt_01.setText("你好,世界") // 设置控件的回调监听 init() } /** * 设置控件的回调监听 */ private fun init() { btn_01.setOnClickListener(this) btn_02.setOnClickListener(this) btn_03.setOnClickListener(this) } /** * 重写OnClickListener接口的onClick方法 */ override fun onClick(p0: View?) { when (p0!!.id) { R.id.btn_01 -> { // 只进行网络请求 network(); } R.id.btn_02 -> { // 进行网路请求,并且进行json数据解析 Toast.makeText(this, "按钮2", Toast.LENGTH_LONG).show() gson(); } R.id.btn_03 -> { Toast.makeText(this, "按钮3", Toast.LENGTH_LONG).show() } } } /** * 网络请求并使用gson解析数据 */ private fun gson() { // 声明要请求的网址,在kotlin中,var能声明一切类型,而后面的:String其实是可以不加的 var string: String = "http://www.wanandroid.com/tools/mockapi/2872/student" // 作用类似java在子线程中进行网络请求,但是async在kotlin中叫做协程 async() { val fore = URL(string).readText() var fromJson: Student = Gson().fromJson(fore, Student::class.java) // 回到UI线程中去更新数据,这里的${属性名}是字符串模板,作用于Java的+属性名+相同 uiThread { txt_01.setText("学生的名字是${fromJson.name},年龄是${fromJson.age}") } } } /** * 网络请求 */ private fun network() { // 声明要请求的网址,在kotlin中,var能声明一切类型,而后面的:String其实是可以不加的 var string: String = "http://www.wanandroid.com/tools/mockapi/2872/student" // 作用类似java在子线程中进行网络请求,但是async在kotlin中叫做协程 async() { val fore = URL(string).readText() Log.d("tonjies", fore) } } /** * 重写OnLongClickListener接口的onLongClick方法 */ override fun onLongClick(p0: View?): Boolean { return false } } 好了,这一小节就到这里啦!在学习的过程中,参考开源项目和巧妙使用Java代码转kotlin的快捷键是挺有用的