前言
Android 官方已经推荐使用Kotlin
足以见Kotlin
的优秀
并且可以在原项目中直接用Kotlin
完全没有什么可担心的
代码比Swift
还好用 强烈推荐
推荐
kotlin 官方文档翻译
From Java to Kotlin(推荐)
Android获取视图实例
项目的配置文件
代码语言:javascript复制buildscript {
ext.kotlin_version = '1.1.51'
//...
dependencies {
//...
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
模块的配置文件
代码语言:javascript复制dependencies {
//...
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
}
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
直接用视图定义的ID即可 超级方便
代码语言:javascript复制<EditText
android:id="@ id/loginNameEditText"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:background="@null"
android:ems="10"
android:hint="请输入用户名"
android:inputType="textPersonName"/>
如上不用再findViewById(R.id. loginNameEditText)
直接用loginNameEditText
就行了
Set/List/Map
首先要说的是没有new
了
集合的分类:
- Set(集)
- List(列表)
- Map(映射)
在Kotlin
中,明确的区分了只读
和可变
的集合
代码如下 前三个是只读 后三个是可变的
var list = listOf<String>("aa", "bb", "cc")
list.forEach { item ->
Log.i("Kotlin", item)
}
var set = setOf<String>("aa", "bb", "cc")
set.forEach { item ->
Log.i("Kotlin", item)
}
val map = mapOf("a" to 1, "b" to 2, "c" to 3)
var map = mapOf<String, String>(Pair("aa", "AA"), Pair("bb", "BB"), Pair("cc", "CC"));
for ((key,value) in map){
Log.i("Kotlin", "key:$key value:$value")
}
var mList = mutableListOf<String>();
mList.add("aa")
Log.i("Kotlin", mList[0])
var mSet = mutableSetOf<String>();
mSet.add("aa")
Log.i("Kotlin", mSet.elementAt(0))
var mMap = mutableMapOf<String, String>()
mMap["aa"] = "AA"
Log.i("Kotlin", "$mMap")
vararg传值
代码语言:javascript复制//普通传递:
varargFun(1,"aaa","bbb","ccc","ddd","fff")
//数组传递:
val strArray = arrayOf("aaa","bbb","ccc","ddd","fff")
varargFun(1,*strArray)
循环
代码语言:javascript复制for (i in 1..4) print(i) //打印1234
for (i in 1 until 4)print(i) //打印123
for (i in 4 downTo 1 step 1) print(i) //打印4321
for (i in (1..4).reversed()) print(i) // prints "4321"
for (i in (1..4).reversed() step 2) print(i) // prints "42"
数据类(pojo)
代码语言:javascript复制data class Customer(val name: String, val email: String)
自动添加的方法:
- 为所有属性添加
getters
,如果为var
类型同时添加setters
- equals()
- haseCode()
- toString()
- copy()
枚举
代码语言:javascript复制enum class Color(val rgb: Int) {
RED(0xFF0000),
GREEN(0x00FF00),
BLUE(0x0000FF)
}
如果不为空执行某操作
代码语言:javascript复制val date = ...
data?.let{
...//如果不为空执行该语句块
}
When 表达式
when 取代了 C 风格语言的 switch
代码语言:javascript复制when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> { // Note the block
print("x is neither 1 nor 2")
}
}
类扩展
代码语言:javascript复制fun <T> MutableList<T>.swap(x: Int, y: Int) {
val tmp = this[x] // 'this' corresponds to the list
this[x] = this[y]
this[y] = tmp
}
调用方式
代码语言:javascript复制val l = mutableListOf(1, 2, 3)
l.swap(0, 2)// 在 `swap()` 函数中 `this` 持有的值是 `l`
扩展是被
静态解析
的
类对比
Java
代码语言:javascript复制Intent t = new Intent();
t.setClass(this,LoginActivity.class);
startActivity(t);
Kotlin
代码语言:javascript复制val t = Intent()
t.setClass(this, LoginActivity::class.java)
startActivity(t)
自定义输出日志
代码语言:javascript复制object LoggerPrinter {
private val MIN_STACK_OFFSET = 3
private val TOP_LEFT_CORNER = '╔'
private val BOTTOM_LEFT_CORNER = '╚'
private val MIDDLE_CORNER = '╟'
private val HORIZONTAL_DOUBLE_LINE = '║'
private val DOUBLE_DIVIDER = "════════════════════════════════════════════"
private val SINGLE_DIVIDER = "────────────────────────────────────────────"
val TOP_BORDER = TOP_LEFT_CORNER DOUBLE_DIVIDER DOUBLE_DIVIDER
val BOTTOM_BORDER = BOTTOM_LEFT_CORNER DOUBLE_DIVIDER DOUBLE_DIVIDER
val MIDDLE_BORDER = MIDDLE_CORNER SINGLE_DIVIDER SINGLE_DIVIDER
val JSON_INDENT = 2
fun getStackOffset(trace: Array<StackTraceElement>): Int {
var i = MIN_STACK_OFFSET
while (i < trace.size) {
val e = trace[i]
val name = e.className
if (name != LoggerPrinter::class.java.name && name != L::class.java.name) {
return --i
}
i
}
return -1
}
}
L类
代码语言:javascript复制import android.util.Log
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
object L {
enum class LogLevel {
ERROR {
override val value: Int
get() = 0
},
WARN {
override val value: Int
get() = 1
},
INFO {
override val value: Int
get() = 2
},
DEBUG {
override val value: Int
get() = 3
};
abstract val value: Int
}
private var TAG = "SAF_L"
var logLevel = LogLevel.DEBUG // 日志的等级,可以进行配置,最好在Application中进行全局的配置
@JvmStatic
fun init(clazz: Class<*>) {
TAG = clazz.simpleName
}
/**
- 支持用户自己传tag,可扩展性更好
- @param tag
*/
@JvmStatic
fun init(tag: String) {
TAG = tag
}
@JvmStatic
fun e(msg: String) {
if (LogLevel.ERROR.value <= logLevel.value) {
if (msg.isNotBlank()) {
val s = getMethodNames()
Log.e(TAG, String.format(s, msg))
}
}
}
@JvmStatic
fun w(msg: String) {
if (LogLevel.WARN.value <= logLevel.value) {
if (msg.isNotBlank()) {
val s = getMethodNames()
Log.e(TAG, String.format(s, msg))
}
}
}
@JvmStatic
fun i(msg: String) {
if (LogLevel.INFO.value <= logLevel.value) {
if (msg.isNotBlank()) {
val s = getMethodNames()
Log.i(TAG, String.format(s, msg))
}
}
}
@JvmStatic
fun d(msg: String) {
if (LogLevel.DEBUG.value <= logLevel.value) {
if (msg.isNotBlank()) {
val s = getMethodNames()
Log.d(TAG, String.format(s, msg))
}
}
}
@JvmStatic
fun json(json: String) {
var json = json
if (json.isBlank()) {
d("Empty/Null json content")
return
}
try {
json = json.trim { it <= ' ' }
if (json.startsWith("{")) {
val jsonObject = JSONObject(json)
var message = jsonObject.toString(LoggerPrinter.JSON_INDENT)
message = message.replace("n".toRegex(), "n║ ")
val s = getMethodNames()
println(String.format(s, message))
return
}
if (json.startsWith("[")) {
val jsonArray = JSONArray(json)
var message = jsonArray.toString(LoggerPrinter.JSON_INDENT)
message = message.replace("n".toRegex(), "n║ ")
val s = getMethodNames()
println(String.format(s, message))
return
}
e("Invalid Json")
} catch (e: JSONException) {
e("Invalid Json")
}
}
private fun getMethodNames(): String {
val sElements = Thread.currentThread().stackTrace
var stackOffset = LoggerPrinter.getStackOffset(sElements)
stackOffset
val builder = StringBuilder()
builder.append(LoggerPrinter.TOP_BORDER).append("rn")
// 添加当前线程名
.append("║ " "Thread: " Thread.currentThread().name).append("rn")
.append(LoggerPrinter.MIDDLE_BORDER).append("rn")
// 添加类名、方法名、行数
.append("║ ")
.append(sElements[stackOffset].className)
.append(".")
.append(sElements[stackOffset].methodName)
.append(" ")
.append(" (")
.append(sElements[stackOffset].fileName)
.append(":")
.append(sElements[stackOffset].lineNumber)
.append(")")
.append("rn")
.append(LoggerPrinter.MIDDLE_BORDER).append("rn")
// 添加打印的日志信息
.append("║ ").append("%s").append("rn")
.append(LoggerPrinter.BOTTOM_BORDER).append("rn")
return builder.toString()
}
fun String.isBlank(msg: String): Boolean {
return msg == null || msg.length == 0;
}
fun String.isNotBlank(msg: String): Boolean {
return !msg.isBlank();
}
}
接口写法对比
Java
代码语言:javascript复制OkGo.<TUserBean>post("")
.params("","")
.execute(new JsonCallback<TUserBean>() {
@Override
public void onSuccess(Response<TUserBean> response) {
}
@Override
public void onFinish() {
super.onFinish();
}
});
Kotlin
代码语言:javascript复制OkGo.post<TUserBean>("")
.params("", "")
.execute(object : JsonCallback<TUserBean>() {
override fun onSuccess(response: Response<TUserBean>) {
}
override fun onFinish() {
super.onFinish()
}
})
静态属性和方法
Kotlin中定义
代码语言:javascript复制class ApiModel {
companion object {
val baseUrl = "http://www.psvmc.cn"
fun getName(): String {
return "小明"
}
}
}
Kotlin中调用
代码语言:javascript复制ApiModel.baseUrl
ApiModel.getName()
Java中调用
代码语言:javascript复制ApiModel.Companion.getBaseUrl();
ApiModel.Companion.getName();
所以建议静态属性和方法建议还用
Java
来写
可见修饰符
- private:同一类或文件(针对包级别定义)中可见
- protected:同private 加子类可见
- internal:在同一个模块中可见(如果声明范围的所有者是可见的)
- public:公共,所有都可见
继承
自定义组件
代码语言:javascript复制open class SpliterLinearLayout : LinearLayoutCompat {
constructor(context: Context) : super(context) {
}
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
}
}