目前Java 8的新特性Lambda 结合 RxJava 在一起使用可以简化大量的代码,下面简单介绍在AndroidStudio中配置Gradle使得支持Java 8。
在project层的build.gradle配置
buildscript {
repositories {
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.0'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
classpath 'me.tatarka:gradle-retrolambda:3.2.5' //添加插件retrolambda
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'me.tatarka:gradle-retrolambda:3.2.4' //for java 8 lamda
}
}
apply plugin: 'com.android.application'
apply plugin: 'me.tatarka.retrolambda'
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
applicationId "com.mrljdx.sample"
minSdkVersion 10
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
//java版本8
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
.....//省略其他配置
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
testCompile 'junit:junit:4.12'
//java 8 配置
retrolambdaConfig 'net.orfjackal.retrolambda:retrolambda:+'
}
配置proguard.pro混淆文件
## see https://github.com/evant/gradle-retrolambda for java 8
-dontwarn java.lang.invoke.*
lambda表达式取代了匿名内部类,取消了模板,允许程序猿用函数式风格编写代码,使代码可读性更高,尽管刚开始你会看不懂,但是你应该尝试,毕竟这是新的东西,我已从中获益。
基本格式是:() -> {}
有下面三种具体表达:
1.(params) -> expression
2.(params) -> statement
3.(params) -> {statement}
传统的点击事件,应用匿名内部类:
Button button = new Button(mContext);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(mContext, "button click", Toast.LENGTH_SHORT).show();
}
});
}
使用lambda表达式之后是这样的
button.setOnClickListener(v -> Toast.makeText(mContext, "button click", Toast.LENGTH_SHORT).show());
一行代码就搞定了,清晰可见,把行为传到了函数里,这里注意v不可省略,是函数onClick的参数;
new Thread(new Runnable() {
@Override
public void run() {
Log.i("TAG", "haha");
}
}).start();
使用lambda表达式之后是这样的:
new Thread(() -> {
Log.i("TAG", "haha");
}).start();
List<String> features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
for (String feature : features) {
System.out.println(feature);
}
// Java 8之后:
List features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
features.forEach(n -> System.out.println(n));
// 使用Java 8的方法引用更方便,方法引用由::双冒号操作符标示,
// 看起来像C++的作用域解析运算符
features.forEach(System.out::println);
输出结果:
Lambdas
Default Method
Stream API
Date and Time API
除了在语言层面支持函数式编程风格,Java 8也添加了一个包,叫做 java.util.function。它包含了很多类,用来支持Java的函数式编程。其中一个便是Predicate,使用 java.util.function.Predicate 函数式接口以及lambda表达式,可以向API方法添加逻辑,用更少的代码支持更多的动态行为。下面是Java 8 Predicate 的例子,展示了过滤集合数据的多种常用方法。Predicate接口非常适用于做过滤。
public static void main(args[]){
List languages = Arrays.asList("Java", "Scala", "C++", "Haskell", "Lisp");
System.out.println("Languages which starts with J :");
filter(languages, (str)->str.startsWith("J"));
System.out.println("Languages which ends with a ");
filter(languages, (str)->str.endsWith("a"));
System.out.println("Print all languages :");
filter(languages, (str)->true);
System.out.println("Print no language : ");
filter(languages, (str)->false);
System.out.println("Print language whose length greater than 4:");
filter(languages, (str)->str.length() > 4);
}
public static void filter(List names, Predicate condition) {
for(String name: names) {
if(condition.test(name)) {
System.out.println(name + " ");
}
}
}
输出结果:
Languages which starts with J :
Java
Languages which ends with a
Java
Scala
Print all languages :
Java
Scala
C++
Haskell
Lisp
Print no language :
Print language whose length greater than 4:
Scala
Haskell
// 更好的办法
public static void filter(List names, Predicate condition) {
names.stream().filter((name) -> (condition.test(name))).forEach((name) -> {
System.out.println(name + " ");
});
}
上个例子说到,java.util.function.Predicate 允许将两个或更多的 Predicate 合成一个。它提供类似于逻辑操作符AND和OR的方法,名字叫做and()、or()和xor(),用于将传入 filter() 方法的条件合并起来。例如,要得到所有以J开始,长度为四个字母的语言,可以定义两个独立的 Predicate 示例分别表示每一个条件,然后用 Predicate.and() 方法将它们合并起来,如下所示:
// 甚至可以用and()、or()和xor()逻辑函数来合并Predicate,
// 例如要找到所有以J开始,长度为四个字母的名字,你可以合并两个Predicate并传入
Predicate startsWithJ = (n) -> n.startsWith("J");
Predicate fourLetterLong = (n) -> n.length() == 4;
names.stream()
.filter(startsWithJ.and(fourLetterLong))
.forEach((n) -> System.out.print("nName, which starts with 'J' and four letter long is : " + n));
…还有很多使用方法详细查看:Java8 lambda表达式10个示例
既然lambda表达式即将正式取代Java代码中的匿名内部类,那么有必要对二者做一个比较分析。
第一个关键的不同点就是关键字 this。匿名类的 this 关键字指向匿名类,而lambda表达式的 this 关键字指向包围lambda表达式的类。
第二是编译方式。Java编译器将lambda表达式编译成类的私有方法。使用了Java 7的 invokedynamic 字节码指令来动态绑定这个方法。
参考:Android Studio 配置
jdk1.8新特性之lambda表达式及在Android Studio中的使用
Java8 lambda表达式10个示例
Java 8简明教程