使用Kotlin实现Android简单Demo,对比JAVA实现分析具体语法不同之处(二)
写在之前,上篇简单的实现了Kotlin工程文件的创建,并记录了默认生成代码与JAVA实现的差别,本篇就整个Demo的编码列举出与JAVA语法的不同之处。
实现的Demo效果如下,头部轮播图+RecyclerView
项目地址:git@github.com:M075097/kotlin_android_demo.git
一.页面布局,依然使用XML方式布局(代码布局分离个人感觉比较好一点),代码如下
activity_main.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">
<!-- 头部标题栏titlebar-->
<RelativeLayout
android:id="@+id/linearlayout_topbar_kotlindemo"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="@color/colorPrimary">
<ImageView
android:id="@+id/imageview_topbar_back"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp"
android:src="@drawable/ic_back"/>
<TextView
android:id="@+id/textview_first"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Demo展示页面"/>
</RelativeLayout>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager_kotlindemo"
android:layout_width="match_parent"
android:layout_height="120dp"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerview_kotlindemo"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
二.MainActivity.kt代码如下
package com.yunzhongjun.weiyang.kotlindemo
import android.os.Bundle
import android.support.v4.view.ViewPager
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import com.yunzhongjun.weiyang.kotlindemo.data.BaseItemData
import com.yunzhongjun.weiyang.kotlindemo.data.ItemNormalData
import com.yunzhongjun.weiyang.kotlindemo.data.ItemTitleData
//继承自父类AppCompatActivity 实现接口 View.OnClickListener 对比JAVA实现为 class MainActivity extends AppCompatActivity implements View.OnClickListener{}
class MainActivity : AppCompatActivity(), View.OnClickListener {
var textView: TextView? = null//变量声明---需要初始化,想要初始化为null 则必须使用A?类型
var mRecyclerView: RecyclerView? = null
var mViewPager: ViewPager? = null
var backButton: ImageView? = null
//var mDataList: List<BaseItemData>? = null;
var mDataList: MutableList<BaseItemData>? = null;//Kotlin中的ArrayList声明之后,不能再增删元素,需要使用MutableList代替。泛型使用和JAVA类似
var adapter: MyRecyclerViewAdapter? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)//调用父类中被覆写的方法,和JAVA中一样
setContentView(R.layout.activity_main)
initData()
initView()
}
//方法声明
private fun initData() {
var titleData: ItemTitleData? = null
var normalData: ItemNormalData? = null
mDataList = mutableListOf<BaseItemData>()
for (i in 1..4) {// for循环
titleData = ItemTitleData()
titleData.title = "分类标题" + i
mDataList!!.add(titleData)//直接使用mDataList.add()时,报错,原因是mDataList声明的类型为A?的类型,要想使用,需要 A? as A 之后使用或者在确认为非空之后直接使用A?的实例a!! Kotlin 会把A?智能转换A
for (j in 1..5) {
normalData = ItemNormalData();
normalData.itemDes = "类型" + i + "下:" + "条目" + j
normalData.itemIconPath = null;
mDataList!!.add(normalData)
}
}
}
private fun initView() {
textView = findViewById(R.id.textview_first) as TextView //强转类型,对比JAVA的(AA)A 实现 Kotlin直接使用 AA as A
mRecyclerView = findViewById(R.id.recyclerview_kotlindemo) as RecyclerView
mViewPager = findViewById(R.id.viewpager_kotlindemo) as ViewPager
backButton = findViewById(R.id.imageview_topbar_back) as ImageView
backButton?.setOnClickListener(this)
var str: String = "Kotlin Demo 页面"
textView?.setText(str)//T此处必须有?号因为A?和A不是同一种类型
//init ViewPager
var viewPagerAdapter:MyViewPagerAdapter = MyViewPagerAdapter(3);//新建对象 不需要使用new 类比JAVA 语法:MyViewPagerAdapter viewPagerAdapter = new MyViewPagerAdapter(3);
mViewPager?.adapter = viewPagerAdapter //对象中原有的set/get方法只要符合标准的setter和getter命名规则 则可以直接使用A.property 赋值 其底层依然是调用setter和getter方法
//init RecyclerView
var layoutManager: LinearLayoutManager = LinearLayoutManager(this)
mRecyclerView?.layoutManager = layoutManager;
adapter = MyRecyclerViewAdapter(mDataList)
//adapter?.setDataList(mDataList)
mRecyclerView?.adapter = adapter
}
//接口方法覆写
override fun onClick(v: View?) {
when (v?.id) {
R.id.imageview_topbar_back -> {
this.finish()
}
else -> {
//TODO nothing
}
}
//when 语法实现类比于JAVA中的
/* switch(v.getId()){
case R.id.imageview_topbar_back:
break;
default:
break;
}*/
}
}
对比以上具体代码可以看到的Kotlin与JAVA代码差别有以下区别
- 1.类继承和实现接口的语法不同,Kotlin中不需要使用extends和implements 来区分声明,统一使用”:”声明
Kotlin继承父类和实现接口如下:
class MainActivity : AppCompatActivity(), View.OnClickListener {
//code what you want!
}
Java实现如下:
class MainActivity extends AppCompatActivity implements View.OnClickListener{
//code what you want!
}
2.继承父类时如果父类没有显式的构造类(constructor)的实现,则需要在父类名后面加上()以表明使用其默认空参的构造函数
代码如下
class MainActivity : AppCompatActivity()//此处需要有()
3.变量声明方式不同,变量用var关键字,常量使用val关键字,以Android中的TextView的声明为例
Kotlin中的TextView变量声明如下:
var textView: TextView? = null//变量声明---需要初始化,想要初始化为null 则必须使用A?类型
若直接使用则可以如下(不需要加?标识)
var textView1:TextView = findViewById(R.id.textview_first) as TextView
对比Java中的如下:
TextView textView;
4.方法(函数)的声明不同
Kotlin中 格式如下private fun functionName(a:A,b:B):C{}
* Kotlin中使用fun关键字声明, * 方法参数为(变量名:变量类型) * 若参数为多个则中间用“,”分开 * 返回值类型声明则在方法体前和参数之后加上":"进行明 * Kotlin中方法也可以使用private,public声明
对比JAVA 中的格式为 :private C functionName(A a,B b){}
5.List使用不同 以ArrayList为例,Kotlin中区分了可变的和不可变的集合,以便准确控制集合什么时候可以更改什么时候不可以更改。进而可以控制不必要的bug生成及编写出一个稳定性更高的API 参考链接https://stackoverflow.com/questions/37913252/kotlins-list-missing-add-remove-etc
Kotlin具体使用中如做如下集合的声明
var mDataList: List<>? = ArrayList<>();
则在使用中mDataList?.add()中会报如下错误
smartcast is not impossible,beacuse “mDataList” is mutable property that could have been changed by this time
####因此此处需要使用Kotlin中提供的集合类型MutableList,声明如下
var mDataList: MutableList<BaseItemData>? = null;//代码摘自MainActivity.kt
初始化如下
mDataList = mutableListOf<BaseItemData>()//代码摘自MainActivity.kt
使用如下
mDataList?.add(normalData)//代码摘自MainActivity.kt
6.for循环使用不同
Kotlin中的使用代码如下
for (j in 1..5) {//此处1..5 相当于数组[1,2,3,4,5]
//do what you want
}
对比JAVA中的一种写法如下int[] aa = new int[]{1,2,3,4,5};
for(int i:aa){
//do what you want
}7.强转类型使用不同,以TextView的强转对比如下
Kotlin中的强转如下
//findViewById()默认返回为View类型,要想被声明为TextView类型的textView接收 需要做以下强转
textView = findViewById(R.id.textview_first) as TextView //强转类型,对比JAVA的(AA)A 实现 Kotlin直接使用 AA as A
对比JAVA实现如下
textView = (TextView)findViewById(R.id.textview_first);
- 8.对象实例化差别,就该Demo中自定义的MyViewPagerAdapter实例化对比
Kotlin中对象实例化如下,最大的不同是不需使用关键字“new”
var viewPagerAdapter:MyViewPagerAdapter = MyViewPagerAdapter(3)
JAVA中的对象实例化为
MyViewPagerAdapter viewPagerAdapter = new MyViewPagerAdapter(3);
- 9.原有对象中符合setter和getter命名规则方法的使用的区别–以原生ViewPager设置Adapter的方法(该方法符合setter和getter规则)对比
Kotlin工程中设置Adapter,可以直接使用类似js中的属性赋值的方式对其进行设置
mViewPager?.adapter = viewPagerAdapter
JAVA中的使用如下
mViewPager.setAdapter(viewPagerAdapter);
- 10.switch 语法差别
Kotlin中使用when实现类似JAVA中的switch语法结构,具体以MainActivity.kt中onclick(View view){}中的实现对比
when (v?.id) {
R.id.imageview_topbar_back -> {
this.finish()
}
else -> {//相当于switch中的default
//TODO nothing
}
}
JAVA中的是实现如下
switch(v.getId()){
case R.id.imageview_topbar_back:
break;
default:
break;
}
三.ViewPager使用的MyViewPagerAdapter定义代码如下
MyViewPagerAdapter.kt
package com.yunzhongjun.weiyang.kotlindemo
import android.support.v4.view.PagerAdapter
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
/**
* Created by weiyang on 2017/7/11 0011.
*/
class MyViewPagerAdapter(pageCount: Int) : PagerAdapter() {
private var pageCount: Int
init {
this.pageCount = pageCount;
}
override fun isViewFromObject(view: View?, `object`: Any?): Boolean {
return view == `object`;
}
override fun getCount(): Int {
return pageCount
}
override fun destroyItem(container: ViewGroup?, position: Int, `object`: Any?) {
container?.removeView(`object` as View)
//super.destroyItem(container, position, `object`)
}
override fun instantiateItem(container: ViewGroup?, position: Int): Any {
var imageView: ImageView? = ImageView(container?.context);
var resId: Int
when (position) {
0 -> {
resId = R.drawable.image_2
}
1 -> {
resId = R.drawable.image_3
}
2 -> {
resId = R.drawable.image_4
}
else -> {
resId = R.drawable.image_aa
}
}
imageView?.setImageDrawable(container?.context?.resources?.getDrawable(resId))
var layoutParams: ViewGroup.LayoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
imageView?.layoutParams = layoutParams
imageView?.scaleType =ImageView.ScaleType.CENTER_CROP
container?.addView(imageView)
return imageView!!
}
}
对比JAVA实现可以看到该类实现的构造方法与JAVA不同
- 构造函数实现的差别如下,Kotlin中class声明时在类名后的()内可以跟上默认的构造函数,但是该默认的构造函数的其他操作需要放到 init{}中进行,该构造函数称为主构造函数
具体详细的关于Kotlin中Class的主构造函数和次构造函数参考http://www.runoob.com/kotlin/kotlin-class-object.html
Kotlin实现如下
class MyViewPagerAdapter(pageCount: Int) : PagerAdapter() {
private var pageCount: Int
init {
this.pageCount = pageCount;
}
//其他覆写的方法
//...
}
JAVA实现如下
public class MyViewPagerAdapter extends PagerAdapter{
private int pageCount;
public MyViewPagerAdapter(int pageCount){
//super();//隐藏的调用父类的默认构造函数
this.pageCount = pageCount;
}
}
四.其他该Demo中能够直接参考的Kotlin和JAVA语法不同的地方
- 1.静态方法的实现(具体参考该Demo中的BaseItemData.kt)
- JAVA中使用static关键字声明
- Kotlin中则需要使用 companion object {} 包括相关方法
- 2.枚举类的实现
具体代码如下:BaseItemData.kt
package com.yunzhongjun.weiyang.kotlindemo.data
/**
* Created by weiyang on 2017/7/11 0011.
*/
abstract class BaseItemData {
abstract fun getItemType(): ItemType
enum class ItemType(typeValue: Int) {
TypeNormal(0),
TypeTitle(1),
Unsupport(2);
var typeValue: Int
init {
this.typeValue = typeValue;
}
companion object {
//类比JAVA中的静态方法
fun getTypeValue(typeValue: Int): ItemType {
for (value in values()) {
if (value.typeValue == typeValue) {
return value;
}
}
return Unsupport;
}
}
}
}
- 3 当一个实例使用类似A?声明后(A为具体的类名),若要调用部分属性时可能会报错,显示类型为nullable,则此时可以在确认其不为null时使用断言A!!把A?转换为A
对应示意代码如下
var a:A? = null
a!!.property//相关属性调用