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

本文介绍了如何使用Kotlin在Android Studio中创建一个简单的Activity。在学习了Kotlin基本语法后,作者通过手动编写一个demo来实践。文章讨论了Kotlin中的继承、类型转换、变量定义以及如何遍历含自定义对象的MutableList。同时,还展示了XML布局、数据模型、Adapter的创建以及必要的build.gradle配置。最后,展示了运行结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  最近,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.activity

import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.GridLayoutManager
import android.support.v7.widget.RecyclerView
import com.example.wl.mubanapplication.R
import com.example.wl.mubanapplication.help_class.ContextHelper
import com.example.wl.mubanapplication.model.Url
import com.example.wl.mubanapplication.ui.view.DividerItemDecoration
import com.wl.adapter.AdapterPopularLocationKotlin
import 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: SecondModelKotlin
if (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: SecondModelKotlin
if (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.adapter

import android.content.Context
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.RelativeLayout
import android.widget.TextView
import com.bumptech.glide.Glide
import com.example.wl.mubanapplication.R
import com.example.wl.mubanapplication.help_class.ContextHelper
import com.example.wl.mubanapplication.ui.view.RoundImageView
import com.wl.model.SecondModelKotlin
import 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()
}


最终运行结果如下:



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










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值