如何用Kotlin实现一个简单的Activity

来源:互联网 发布:中科院学位论文数据库 编辑:程序博客网 时间:2024/05/29 05:01

  最近,Google公司正式宣布在Studio支持Kotlin语言开发Andriod,并支持java文件直接转变为kt(kotlin)文件。在初步学习了Kotlin基本语法后,忍不住code一下,最开始是直接将项目中的java文件转变为kt文件,但发现很多地方还是会报错,需要手动修改, 很是麻烦,所以用Kotlin后面手写了一个demo。


首先,activity_main的xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context="com.wl.activity.MainActivity">    <android.support.v7.widget.RecyclerView        android:id="@+id/recyclerView"        android:layout_width="match_parent"        android:layout_height="match_parent" /></LinearLayout>
  准备用RecyclerView实现一个简单的GridLayoutManager布局,所以Activity代码:

package com.wl.activityimport android.os.Bundleimport android.support.v7.app.AppCompatActivityimport android.support.v7.widget.GridLayoutManagerimport android.support.v7.widget.RecyclerViewimport com.example.wl.mubanapplication.Rimport com.example.wl.mubanapplication.help_class.ContextHelperimport com.example.wl.mubanapplication.model.Urlimport com.example.wl.mubanapplication.ui.view.DividerItemDecorationimport com.wl.adapter.AdapterPopularLocationKotlinimport com.wl.model.SecondModelKotlin@Suppress("UNUSED_EXPRESSION")class MainActivity : AppCompatActivity() {    private val MARGIN = 20    override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContentView(R.layout.activity_main)        val recylerView = findViewById(R.id.recyclerView) as RecyclerView        val layoutManager = GridLayoutManager(ContextHelper.getApplicationContext(), 2)        val decoration = DividerItemDecoration(ContextHelper.getApplicationContext(), R.drawable.divider, R.color.transparent)        decoration.setSize(MARGIN)        decoration.setType(DividerItemDecoration.BORDER)        recylerView.addItemDecoration(decoration)        recylerView.layoutManager = layoutManager        val mAdapter = AdapterPopularLocationKotlin(mContext = ContextHelper.getApplicationContext())        mAdapter.setData(getSecondModelsKotlin() as MutableList<SecondModelKotlin>)        recylerView.adapter = mAdapter        val list: MutableList<SecondModelKotlin>? = getNames() as MutableList<SecondModelKotlin>?//?允许非空,不加?的话,一直不为空        val datas: MutableList<SecondModelKotlin> = ArrayList()        var model: SecondModelKotlin        if (list != null) {//            for (i in list.indices) {//                model = list[i]//                model.name = "Liszt" + i//                datas.add(model)//            }            for (i in list) {                model = i                model.name = "Liszt" + list.indexOf(model)                datas.add(model)            }            mAdapter.setData(datas)        } else {            mAdapter.setData(getSecondModelsKotlin() as MutableList<SecondModelKotlin>)        }            print(max(2,6))    }    fun max(a: Int, b: Int) = if (a > b) a else b//fun 方法,如果a>b,return a ,else return b;    fun getSecondModelsKotlin(): List<SecondModelKotlin> {        val list = ArrayList<SecondModelKotlin>()        val model1 = SecondModelKotlin()        model1.text = "Hello 1"        model1.avatarUrl = Url.IMAGE_URL_FRANCE_1        model1.name = "Marks 1"        list.add(model1)        val model2 = SecondModelKotlin()        model2.text = "Hello 2"        model2.avatarUrl = Url.IMAGE_URL_FRANCE_2        model2.name = "Marks 2"        list.add(model2)        val model3 = SecondModelKotlin()        model3.text = "Hello 3"        model3.avatarUrl = Url.IMAGE_URL_FRANCE_3        model3.name = "Marks 3"        list.add(model3)        val model4 = SecondModelKotlin()        model4.text = "Hello 4"        model4.avatarUrl = Url.IMAGE_URL_FRANCE_4        model4.name = "Marks 4"        list.add(model4)        val model5 = SecondModelKotlin()        model5.text = "Hello 5"        model5.avatarUrl = Url.IMAGE_URL_FRANCE_2        model5.name = "Marks 5"        list.add(model5)        val model6 = SecondModelKotlin()        model6.text = "Hello 1"        model6.avatarUrl = Url.IMAGE_URL_FRANCE_3        model6.name = "Marks 1"        list.add(model6)        val model7 = SecondModelKotlin()        model7.text = "Hello 2"        model7.avatarUrl = Url.IMAGE_URL_FRANCE_4        model7.name = "Marks 2"        list.add(model7)        val model8 = SecondModelKotlin()        model8.text = "Hello 3"        model8.avatarUrl = Url.IMAGE_URL_FRANCE_1        model8.name = "Marks 3"        list.add(model8)        val model9 = SecondModelKotlin()        model9.text = "Hello 4"        model9.avatarUrl = Url.IMAGE_URL_FRANCE_2        model9.name = "Marks 4"        list.add(model9)        val model10 = SecondModelKotlin()        model10.text = "Hello 5"        model10.avatarUrl = Url.IMAGE_URL_FRANCE_4        model10.name = "Marks 5"        list.add(model10)        return list    }    fun getNames(): List<SecondModelKotlin>? {        var model: SecondModelKotlin        val list = java.util.ArrayList<SecondModelKotlin>()        for (i in 0..49) {            model = SecondModelKotlin()            model.name = "hello-" + i            list.add(model)        }//        return list        return null    }}


    这个Activity的代码有很多地方与java很相似,但有不同,有种似是而非的感觉,具体解释一下:

    如MainActivity类名的定义,class MainActivity:AppCompatActivity(), 后面的AppCompatActivity()按java的理解应该是MainActivity需要继承的父类,kotlin中用“:”来表示继承关系;

    val recylerView = findViewById(R.id.recyclerView) as RecyclerView
    这句代码,我们肯定知道是在初始化控件,通过findViewById这个方法。但是注意后面的“as RecyclerView”,我们知道java中,findViewById后,都需要做强制类型转换,而RecyclerView明显是这个View需要转换的类型,所以Kotlin

中用“as”来表示强制类型转换。这里还有一个值得一说的知识点是,Kotlin中变量都用val来定义,常量都用var。例:

val a:String = “Hello World”,val b:Int = 1,前一个定义了一个String类型的变量a,后一个定义了一个Int类型的变量b。

    val layoutManager = GridLayoutManager(ContextHelper.getApplicationContext(), 2)

    这里需要注意怎么获取对象,java中获取对象通常都是new 对象的构造函数,kotlin中直接通过调用对象的构造函数就可获取对象。

val mAdapter = AdapterPopularLocationKotlin(mContext = ContextHelper.getApplicationContext())mAdapter.setData(getSecondModelsKotlin() as MutableList<SecondModelKotlin>)recylerView.adapter = mAdapter
    这几句我们大致会知道是初始化Adapter及数据,但最后一句,却让人有点难理解,初一看,类似java中的赋值代码,但实际上在Kotlin中却等同于java中的“recylerView.setAdapter(mAdapter)”,另外,Kotlin中不再使用java中List来收集数据, 而是使用MutableList替代。


fun getNames(): List<SecondModelKotlin>? {        var model: SecondModelKotlin        val list = java.util.ArrayList<SecondModelKotlin>()        for (i in 0..49) {            model = SecondModelKotlin()            model.name = "hello-" + i            list.add(model)        }//        return list        return null    }
    这里主要要看的是Kotlin中的For循环语法。可以看出Kotlin的for循环较之Java的for循环更简洁,没有初始化条件,判断条件,及控制语句,直接就是 “i in 0..49”,我们大致可以猜出i表示遍历时候的索引,而"0..49",表示遍历的范围,所以“in”可以顾名思义,表示一个判断:当i还在0-49的范围之内(i 可以等于49),for循环继续,否则for循环停止。


val list: MutableList<SecondModelKotlin>? = getNames() as MutableList<SecondModelKotlin>?//?允许非空,不加?的话,一直不为空val datas: MutableList<SecondModelKotlin> = ArrayList()var model: SecondModelKotlinif (list != null) {    for (i in list.indices) {        model = list[i]        model.name = "Liszt" + list.indexOf(model)        datas.add(model)    }    mAdapter.setData(datas)} else {    mAdapter.setData(getSecondModelsKotlin() as MutableList<SecondModelKotlin>)}

    这段代码只要要看的Kotlin如何遍历一个含自定义对象的MutableList。“i in list.indices”,通过后面的“model = list[i]”可知,i表示索引,但是list.indices是什么意思?为了探究,我试着做了下面的一个for循环:

val list: MutableList<SecondModelKotlin>? = getNames() as MutableList<SecondModelKotlin>?//?允许非空,不加?的话,一直不为空val datas: MutableList<SecondModelKotlin> = ArrayList()var model: SecondModelKotlinif (list != null) {    for (i in list) {        model = i        model.name = "Liszt" + list.indexOf(model)        datas.add(model)    }    mAdapter.setData(datas)} else {    mAdapter.setData(getSecondModelsKotlin() as MutableList<SecondModelKotlin>)}
    不难看出,i表示集合中的自定义对象,因此可知,indices表示获取的是当前的索引。

fun getNames(): List<SecondModelKotlin>? {        var model: SecondModelKotlin        val list = java.util.ArrayList<SecondModelKotlin>()        for (i in 0..49) {            model = SecondModelKotlin()            model.name = "hello-" + i            list.add(model)        }//        return list        return null    }
    这里需要学习的是Kotlin中方法的定义。fun表示定义的是方法,getNames(),是方法名,而冒号后面的List<SecondModelKotlin>表示返回值。但是"?"是什么意思。这里需要看这段代码的另一种写法:

fun getNames(): List<SecondModelKotlin> {        var model: SecondModelKotlin        val list = java.util.ArrayList<SecondModelKotlin>()        for (i in 0..49) {            model = SecondModelKotlin()            model.name = "hello-" + i            list.add(model)        }        return list//        return null    }
    这种写法中没有“?”,返回值是List(非空集合);前一种方法,返回值为null,如果不加?,会提示报错,但是加了“?”,则可以返回null。这里是是kotlin比java简洁体现之一,java很多逻辑都要作非空判断,相信大家写得很烦,而kotlin对此作了优化,默认是没有null,如果需要允许有null的情况,则在赋值的时候, 也就是等号左边,加上“?”,如val a : String ?=null , 而val a :String = null是错误的语法

  而数据模型SecondModelKotlin的定义:

class SecondModelKotlin {    var name = ""    var avatarUrl = ""    var text = ""}
这里值得一提的是,Kotlin中没有set,get方法, 并且kotlin推荐将类的属性定义为常量。


最后将Adapter贴上。

package com.wl.adapterimport android.content.Contextimport android.support.v7.widget.RecyclerViewimport android.view.LayoutInflaterimport android.view.Viewimport android.view.ViewGroupimport android.widget.RelativeLayoutimport android.widget.TextViewimport com.bumptech.glide.Glideimport com.example.wl.mubanapplication.Rimport com.example.wl.mubanapplication.help_class.ContextHelperimport com.example.wl.mubanapplication.ui.view.RoundImageViewimport com.wl.model.SecondModelKotlinimport java.util.*class AdapterPopularLocationKotlin(mContext: Context) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {    private var mItemClickListener: OnItemClickListener? = null    private val inflater: LayoutInflater = LayoutInflater.from(mContext)    private var datas: MutableList<SecondModelKotlin>? = null    fun setData(list: MutableList<SecondModelKotlin>) {        if (datas == null) {            datas = ArrayList<SecondModelKotlin>()        }        datas!!.clear()        datas!!.addAll(list)        notifyDataSetChanged()    }    val list: MutableList<SecondModelKotlin>        get() = datas!!    override fun getItemCount(): Int {        return datas!!.size    }    override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, position: Int) {        val holder = viewHolder as ChildViewHolder        val model = datas!![position]        holder.setModel(model)    }    override fun onCreateViewHolder(viewHolder: ViewGroup, viewType: Int): RecyclerView.ViewHolder {        val view = inflater.inflate(R.layout.item_popular_country, null)        val holder = ChildViewHolder(view)        return holder    }    inner class ChildViewHolder(v: View) : RecyclerView.ViewHolder(v) {        internal var iv_image: RoundImageView? = null        internal var tv_area: TextView? = null        internal var model: SecondModelKotlin? = null        internal var rl_parent: RelativeLayout        init {            iv_image = v.findViewById(R.id.iv_image) as RoundImageView            tv_area = v.findViewById(R.id.tv_area) as TextView            rl_parent = v.findViewById(R.id.rl_parent) as RelativeLayout        }        fun setModel(model: SecondModelKotlin) {            Glide.with(ContextHelper.getApplicationContext())                    .load(model.avatarUrl)                    .centerCrop()                    .error(R.drawable.avatar_default_black)                    .into(iv_image)            tv_area!!.text = model.name        }    }}

清单文件注册申明activity:

<activity    android:name="com.wl.activity.MainActivity"    android:label="@string/title_activity_main"    android:theme="@style/AppTheme">    <intent-filter>        <action android:name="android.intent.action.MAIN" />    </intent-filter></activity>

build.gradle中配置如下:

apply plugin: 'kotlin-android'

android {    compileSdkVersion 25    buildToolsVersion "25.0.1"    defaultConfig {        applicationId "com.example.haoyuban111.mubanapplication"        minSdkVersion 19        targetSdkVersion 25        versionCode 1        versionName "1.0"        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"        multiDexEnabled true    }    buildTypes {        release {            minifyEnabled false            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'        }    }    sourceSets {        main.java.srcDirs += 'src/main/kotlin'    }}


dependencies {    compile fileTree(include: ['*.jar'], dir: 'libs')    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {        exclude group: 'com.android.support', module: 'support-annotations'    })    compile files('libs/nineoldandroids-2.4.0.jar')    //    compile 'com.facebook.fresco:fresco:0.12.0'    //    compile 'com.facebook.fresco:animated-webp:0.12.0'    //    compile 'com.facebook.fresco:webpsupport:0.12.0'    //    compile 'com.facebook.fresco:imagepipeline-okhttp:0.12.0+'    compile files('libs/commons-io-2.4.jar')    compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"    compile 'com.android.support:appcompat-v7:25.1.1'    compile 'com.android.support:support-v4:25.1.1'    compile 'com.android.support:recyclerview-v7:25.1.1'    compile 'com.github.bumptech.glide:glide:3.7.0'    compile 'com.squareup.okhttp3:okhttp:3.6.0'    compile 'com.google.code.gson:gson:2.6.2'    compile 'com.android.support.constraint:constraint-layout:1.0.2'    compile 'com.android.support:design:25.3.1'    testCompile 'junit:junit:4.12'}repositories {    mavenCentral()}


最终运行结果如下:



只是初步学习了一下,讲的很肤浅,希望对大家的学习有帮助吧










原创粉丝点击