聊聊 Android N 開始支持的 Lambda

cmch0440 8年前發布 | 10K 次閱讀 安卓開發 Android開發 移動開發

Android N 正式版已經發布了。對于開發者來說一個重大的更新是對于Java支持到了Java8,其中一點就是支持Lambda。我們就來聊聊什么是lambda,怎么在Android中使用。

什么是lambda

Lambda 可以理解為匿名函數,幫助我們寫出更加簡潔的代碼。

給view設置一個clicklistener,原本你需要寫出這樣的代碼:

v.setOnClickListener(newView.OnClickListener(View v) {
@Override
publicvoidonClick(View v){
 Toast.makeText(getActivity(), "clicked", Toast.LENGTH_LONG).show()
 }
});

使用lambda之后:

.setOnClickListener(v -> Toast.makeText(getActivity(), "clicked", Toast.LENGTH_LONG).show());

是不是代碼量爆減。這里再看下怎么寫lambda。

在JavaScript,python等語言中函數是一等公民,但是Java中類才是。使用lambda時候,lambda其實應該是一個對象,依附于函數式接口(只包含一個抽象方法聲明的接口,例如剛剛我們舉例的 OnClickListener 就是,在Java 8 需要使用 @FunctionalInterface 這樣保證在編譯的時候一個接口只有一個抽象注解)。

寫法的基本規則是這樣:

(arguments) -> {body}

arguments 是參數列表,0~n個, 參數為一個時候,可以不要括號

body 為具體代碼部分,如果代碼只有一句的話可以不要大括號

返回值會自動推導出類型

一些寫法實例:

(inta,intb) -> {returna + b; }

() -> System.out.println("Hello World");

(String s) -> System.out.println(s);

() -> 42

() -> { return3.1415};
(a, b) -> {returna+b;}

另外一點需要注意的是,在我們的lambda表達式中 this 關鍵指的是外部對象,而不是我們以為的lambda這個對象。在語法糖的實現過程中,lambda表達式最后會被變為類的私有方法,因此可以放心的使用this。

使用retrolambda

目前有個比較成熟的解決方案,使用 retrolambd ,接入的配置如下:

apply plugin:'com.android.application'
apply plugin:'me.tatarka.retrolambda'

buildscript {
 repositories {
 mavenCentral()
 }

 dependencies {
 classpath 'me.tatarka:gradle-retrolambda:3.2.5'
 } 
}
// Required because retrolambda is on maven central
repositories {
 mavenCentral() 
}
 android { 
 compileOptions {
 sourceCompatibility JavaVersion.VERSION_1_8
 targetCompatibility JavaVersion.VERSION_1_8 
 }
}
//指定將源碼編譯的級別,以下會將代碼編譯到1.7的自己碼格式
retrolambda {
 javaVersion JavaVersion.VERSION_1_7
}

當前,retrolambda對于android gradle插件是有依賴的,需要使用1.5+的插件才可以。

retrolambda的原理是在編譯的過程中,給class文件增加包裹,轉成java 1.7支持的格式。

使用jack

在Android N,支持使用Java 8, google給我們提供了新的編譯工具 jack ,因此可以直接支持lambda,為了支持低版本的Android也可以用lambda,我們需要將 targetSdkVersion 和 compileSdkVersion 設置為23或者更小。啟用jack,修改 build.gradle 如下。

android {
 ...
 defaultConfig {
 ...
 jackOptions {
 enabled true
 }
 }
 compileOptions {
 sourceCompatibility JavaVersion.VERSION_1_8
 targetCompatibility JavaVersion.VERSION_1_8
 }
}

jack工具鏈會的編譯步驟如下:

Jack (.java --> .jack --> .dex)

和之前相比,將中間轉換為class文件的步驟省略了,不需要多個工具鏈。

在低版本兼容lambda,也同樣是使用的語法糖來實現。

后記

如上兩種工具都可以讓我們在進行Android開發的時候來使用lambda,retrolambda出來的時間更早,經過很多次的迭代,目前也有一些app在使用,相比較來說更加成熟。jack則是google開發,減少了對javac的依賴,更多谷歌的自主性,相信后面谷歌大力推廣的,但是出于剛剛開發出來因此還不夠成熟,對于lint,proguard,instant run還有很多地方支持不好的地方,我們相信以后jack會是趨勢。

出于嘗鮮,還是可以來使用的,但是在大的項目里面還是不建議使用的,畢竟萬一出了問題還是很難排查的。

另外,如果想要在android開發更爽快的使用lambda,也可以去試試 kotlin 這個語言。

參考資料:

  1. http://viralpatel.net/blogs/Lambda-expressions-java-tutorial/
  2. https://developer.android.com/guide/platform/j8-jack.html
  3. https://github.com/evant/gradle-retrolambda

 

 

來自:http://blog.isming.me/2016/09/13/android-lambda/

 

 本文由用戶 cmch0440 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!