最近,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中直接通过调用对象的构造函数就可获取对象。
这几句我们大致会知道是初始化Adapter及数据,但最后一句,却让人有点难理解,初一看,类似java中的赋值代码,但实际上在Kotlin中却等同于java中的“recylerView.setAdapter(mAdapter)”,另外,Kotlin中不再使用java中List来收集数据, 而是使用MutableList替代。val mAdapter = AdapterPopularLocationKotlin(mContext = ContextHelper.getApplicationContext()) mAdapter.setData(getSecondModelsKotlin() as MutableList<SecondModelKotlin>) recylerView.adapter = mAdapter
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() }
最终运行结果如下:
只是初步学习了一下,讲的很肤浅,希望对大家的学习有帮助吧