Lambda的学习成本不高,甚至我觉得挺低的。
想在Android studio中使用lambda,现在来讲有两种方式1.使用jack编辑器(AS2.1+),2.使用lambda的插件me.tatarka.retrolambda。
最简单、方便的是方式1,但是它目前存在一个局限:不能和ButterKnife和dagger一起使用,因为编译是会出现问题。
我试过7.0的Butterknife和jack一起用,能通过编译,程序能安装到真机,但是点击事件失效了;换成8.0的ButterKnife,编译都通不过,会提示一个异常。
具体操作:
1.jack编辑器
在module的gradle中添加如下代码框中的两部分:
提供复制粘贴版:
jackOptions {
enabled true
}
compileOptions {
sourceCompatibility 1.8
targetCompatibility 1.8
}
或者逼格高点:
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
2.retrolambda插件需要Project的gradle和module的gradle都做一些配置:
Project/gradle
提供复制粘贴板:
jcenter()
classpath 'me.tatarka:gradle-retrolambda:3.2.5'
Module/gradle:
提供复制粘贴板:
apply plugin: 'me.tatarka.retrolambda'
另一个前面有
在没有真正使用lambda之前,我感觉我被迷雾的不清:看到一个箭头省略了那多代码,似乎看到了春天和搂不住的未来,然而并不是,它还是有限制的。
对一些接口不是很熟,用lambda可能回有点障碍
Lambda的规则:(parameters) -> expression 或者 (parameters) -> { statements; }
1.参数和箭头不说,出了单个参数时可以省略括号没啥问题了;
2.第一个规则其实是第二个的一种简写。箭头后面的如果是仅有一条的表达式(就是说有返回值且表达式结果就是返回值),忽略掉了分号和大括号。
3.多行代码的实现体肯定要用大括号,有返回值就带上return,没返回值可以不写return。
4.void的方法必须使用大括号{}
使用lambda表达式必须满足一个前提:实现包含且仅包含一个方法(参数任意数量)的接口才可以使用lambda,不然,哪凉快哪待着去......
其实仔细想一下也对,lambda忽略了方法名,那么这种指定必须是唯一的,否则引起错乱可不是闹着玩的。
于是我想,往极端了走会是什么结果?我蛋疼的定义了两个参数类似但是接口名称不同的类,打算给一个普通类添加个两个同名不同参的方法分别设置这两个接口,看看会发生什么,然后我发现自己XX了,从原理上讲:接口定义之后就是根本不在乎你的实现,只要参数分配对了,实现过程是内部类当下写的,所以不存在问题,调度谁也没有问题;从编译器来讲,AS的检查机制提示引起了歧义,代码报了异常,解决方法就是加上一个强制转换。
public interface FirstInterface {
void first(int a, int b);
}
public interface SecondInterface {
void second(int a, int b);
}
public class LambdaTest1 {
private FirstInterface firstInterface;
private SecondInterface secondInterface;
public void setInterface(FirstInterface firstInterface) {
this.firstInterface = firstInterface;
Log.i("LambdaTest1","first");
}
public void setInterface(SecondInterface secondInterface) {
this.secondInterface = secondInterface;
Log.i("LambdaTest1","second");
}
}
实现时报异常截图:
排除异常后截图:
继续折腾下一个:不同返回类型
这个就更简单了,返回的类型决定了哪个是被调用的接口。
public interface IntInterface {
int getInt(int a, int b);
}
public interface VoidInterface {
void getVoid(int a, int b);
}
public class LambdaTest2 {
private IntInterface intInterface;
private VoidInterface voidInterface;
public void setInterface(IntInterface intInterface) {
this.intInterface = intInterface;
}
public void setInterface(VoidInterface voidInterface) {
this.voidInterface = voidInterface;
}
}
调用部分截图:
根据截图,看样子是返回了a+b的int值,那么我们在看一下它到底调用了哪个:
红框内是调用方法,而篮筐部分未被调用。
换一个实现方法体:
调用情况:
上面只是极限情况,如果是自己写成了这样,那你应该多半是有病思维缜密;如果是别人写这样的接口给你调用,你就去打死他多多请教吧。