在本次谷歌IO大會上Kotlin終于轉正成為安卓官方語言。雖然每年都會出來一些編程語言,不過很多都小眾且容易消亡,但這次,由于Oracle和Google的在Java版權問題,以及Google的安卓生態圈保衛戰等原因,這次kotlin多半會真正上位,起碼在安卓開發方面,相信隨著Kotlin的完善和安卓生態圈的繼續成熟,java的使用將越來越少。
本文主要記錄自己學習Kotlin過程中卡住的一些技術點。
1-Kotlin實現Activity之間的跳轉
- 這點其實挺無奈的,在網上找了半天也沒找到最直接準確的,說明資源還是挺缺的。記錄下,其實和java中還是比較像的。kotlin中,使用intent跳轉到其它activity
其中,這里的activity都是kotlin activity:
var intent = Intent(this,SecondActivity::class.java);startActivity(intent)
當然若是使用anko庫的話,跳轉方式為:
startActivity<SecondActivity>(...可傳數據...)
2-Kotlin中匿名內部類
- kotlin接口類似于java jdk8中的接口,具體用法就不介紹了。當使用接口回調時,傳參的匿名內部類的格式稍微復雜些,類似于靜態方法的定義,這里,kotlin中匿名內部類的表示為:
//.kt接口
interface ICallBack {
fun getResult(age:Int)
}
//傳參, 匿名內部類
request.setCallBack(object :ICallBack{
override fun getResult(age: Int) {
}
})
接上,不過匿名內部類在kotlin中使用并不多
3-Kotlin中擴展屬性和函數
- 可以使用類似靜態導入的方式,給一個已存在但不易修改的類,動態的添加屬性和方法,這是比較牛的一個功能。記錄一下
//作為單例對象的類聲明
object Utils {
fun Context.tos(msg: String) {
Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
}
val View.ctx:Context
get() = context
}
== 給所有的activity中植入toast方法,靜態導入packgename.Utils.tos即可,調用tos().
== 在所有的設計view引用的地方植入直接調用屬性,內部實現還是調用的方法靜態導入packgename.Utils.ctx即可,使用方法view.ctx
4-Kotlin中函數參數,多參數的使用
很多教程和博客里基本只提到了單參數的函數作為參數,那個相對比較簡單,就不再贅述。這里只舉個多參數函數的用法,其實也很類似,但是記錄的博客并不多。
首先定義個請求類,有個函數作為參數,該函數需要兩個參數:
class Request2(var callListener:(String,Int) -> Unit) {
fun run() {
val readText = "from request2"
callListener.invoke(readText,12345)
}
}
假如有個btn點擊,完成邏輯,代碼如下:
btn_r1.setOnClickListener{
Request2{text:String,length:Int->
Log.e("flag--","(MainActivity.kt:27)-->>"+text+length);
}.run()
}
此時上述回調里面的log日志便會打印出來。
5-兩個關鍵字:object和data
==data關鍵字,是顯示聲明該類是作為數據類使用,這一點在系統生成的toString()方法中比較容易有對比。沒有使用data的,toString()默認打印對象的內存地址;使用data關鍵字的,默認按照一定規則打印相關屬性。
==object關鍵字,語義是聲明一個對象,這個對象是類級別的,對比于java來說,定義這個類相當于定義了一個全局的單例對象。
6-兩個特殊函數:with和incline
==with函數目前比較明顯的作用是簡化對某個對象的調用。比如
//data類
data class Person(var name: String, var age: Int, var hobby: String) {
}
//使用
with(Person("小明", 29, "吃")) {
Log.e("flag--", "(MainActivity.kt:29)-->>" + name)
Log.e("flag--", "(MainActivity.kt:30)-->>" + age)
Log.e("flag--", "(MainActivity.kt:31)-->>" + hobby)
}
里面的name,age,hobby等默認是with后面的對象的,使用時就不用加前綴了。
==inline內聯函數目前比較明顯的作用是顯示的增加和控制行為。這個有些代理模式的味道,不如動態代理,但是由于函數參數的語法,使得復用性是比較高的。例子:
//內聯函數,本函數包含三個參數,一個str,一個num,一個函數參數,當隨機數小于5將會調用參數函數,
//函數參數接收str和num作為參數:
inline fun numSmaller5(str:String,nums:Int,code: (str: String, age: Int) -> Unit) {
val nextInt = Random().nextInt(10)
when (nextInt) {
in 1..5 -> {
code.invoke(str,nums)
}
}
}
//使用,trywith是真正的執行函數
numSmaller5 ("小明",21){ text:String, num:Int -> tryWith(text,num) }
7-委托,和java中的橋聯模式比較像,假設一個對象有多個屬性和行為,其中某個行為有不同的實現方式,就可以考慮使用橋聯模式,將實現和抽象解耦。這里以委托的方式列下代碼。
//播放視頻的接口
interface IPlayVideo {
fun play()
}
//聲明一個類,具有一個IPlayVideo屬性part,同時該類繼承于IPlayVideo,同時該類的play行為委托給part
class MobilePhone(part:IPlayVideo):IPlayVideo by part {
fun call(contact:String){
Log.e("flag--","(MobilePhone.kt:12)-->>call+$contact");
}
}
//聲明一個IPlayVideo作為實現
class SurfaceView : IPlayVideo {
override fun play() {
Log.e("flag--", "(SurfaceView.kt:17)-->>by surface")
}
}
//調用
var phone = MobilePhone(SurfaceView())
with(phone){
play()
call("110")
}
結果就是兩個log輸出
8-Kotlin中有一些很省事的函數,比如let,with和apply等。let-讓作為參數的函數執行,且返回參數函數的返回值;with-簡化了get等調用;apply-簡化了初始化對象的過程。這些函數用著都會使代碼顯得優雅和小巧。 而且其實現,也并不困難。這里我們也做個類似的函數,來體驗一把創造簡潔代碼的感覺。這里,就拿handler開刀吧。純為體驗,很多功能和細節并不考慮。--by CysionLiu
--handler大家很熟悉了,在使用時從創建,在子線程發送一個消息,再到主線程處理,最簡單的代碼量10行左右吧。但在這里用kotlin的語法稍微處理下。
//創建一個靜態函數,可復用
inline fun <T> T.msg(msg:Message,crossinline f: (msg: Message) -> Unit): Unit {
val handler =object : Handler(Looper.getMainLooper()) {
override fun handleMessage(msg: Message?) {
super.handleMessage(msg)
f.invoke(msg!!)
}
}
handler.sendMessage(msg)
}
//然后在context環境中按如下方式調用。,一看就知道,調用代碼只有3行,還能及時處理消息,轉換線程。
Thread({msg(Message.obtain().apply {what = 880800}){
msg->toast("消息--"+msg.what)
}}).start()
//結果,主線程吐司:消息--880800
接上,其實java也可以寫個函數做,但代碼的簡潔,完全是來自于kotlin語法的靈活。
有關安卓開發方面的一般技術點和語法糖學習完成,以上是個人認為比較有代表性的一些。以后的Kotlin的學習和使用應該更傾向細節深入方面。