Android 使用Java8新特性之Lambda expression (附命令者模式简化)
2017-03-08 16:55
513 查看
前言
Lambda expression,java8的新特性。使用Lambda expression,可以替代只有一个函数的接口实现,告别匿名内部类,代码看起来更简洁易懂。java8还有其它一些新特性,不过在android上可能都无法使用。
studio 2.x后 支持jack编译器,使用它,能使用java8的Lambda expression,但其它特性也不敢保证就能用。
注:Android SDK中集成了JDK的一些源码,有些原生JDK中的类,可能增加了新特性的一些实现,但Android中的并没有。再比如java8的java.util.function包,在低版本中也是没有的
还可以使用插件retrolambda来支持java8的Lambda expression。
Jack 配置
添加如下配置android { jackOptions { enabled true } compileOptions {//jack、retrolambda编译必需 sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } }
以启用jack编译器,来支持Lambda expression
使用最新2.3版studio,jdk 1.8 的环境, gradle2.3,和如上的配置
经测试,在4.4的模拟器上也是可以跑的
配置Demo : https://git.oschina.net/aa86799/testJackSetting
retrolambda 配置
项目地址:https://github.com/evant/gradle-retrolambdaretrolambda 兼容java5、6、7使用Lambda expression。
配置如下
buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:2.2.3' classpath 'me.tatarka:gradle-retrolambda:3.6.0' } } apply plugin: 'me.tatarka.retrolambda' android { defaultConfig { minSdkVersion 11 //这个没有硬性要求 } compileOptions {//jack、retrolambda编译必需 sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } }
注:很多开源的项目,还是使用的retrolambda
Lambda expression的使用方式
首先,我们要知道的是,该表达式,整体上是表达了一个『对象类型』。最简单的Lambda expression
代码:Runnable runnable = () -> System.out.println("hi, 我是 stone"); runnable.run();
()其实就是方法参数列表,这里没有传参数,那么就会去匹配无参的方法,因Runnable只有一个void run(),所以会匹配到它;这里没有写方法名,所以方法的名字会被忽略。
-> 这个后面跟方法体。这里只有一句打印代码,可以省略方法体的花括号:{} 。
注:这里还省略了”new Runnable”这样的代码,是因为编译器会进行自动的类型推断。如果直接调用 () -> System.out.println(“hi, 我是 stone”).run(); 那么是编译不过的,因为编译器不知道去哪个类里找对应的方法
有参数且有返回值的Lambda expression
代码:button.setOnTouchListener((view, event)-> { if (event.getAction() == MotionEvent.ACTION_DOWN) { if (flag) { return true; } } return super.onTouchEvent(event); });
有参数时,只要传参数名字即可,名字可随意定义;类型定义或不定义都可以;不定义时,编译器会自动推断。
有返回值时,可以在方法体中,使用return;也可以在只有一段代码时,省略return,如下:
button.setOnTouchListener((v, e) -> super.onTouchEvent(e));
自定义接口,并使用Lambda expression
首先定义只有一个抽象方法的接口:interface IGetData<T> {//lambda只能用于单一方法类型匹配 T get(); // T getOne(int i); //多个抽象方法,直接编译不过 }
定义方法,参数为上面定义的接口:
void print(IGetData<String> data) { String msg = data.get(); System.out.println(msg); }
使用Lambda expression 作为参数, 调用print():
print(() -> "张三"); print(() -> { System.out.println("干活了"); return "李四"; });
输出:
03-08 06:46:00.430 1510-1510/? I/System.out: 张三 03-08 06:46:00.430 1510-1510/? I/System.out: 干活了 03-08 06:46:00.430 1510-1510/? I/System.out: 李四
使用Lambda expression简化命令者模式
命令者模式的特征及简单实现流程:一个命令者 接口, 定义 一个统一执行命令的抽象方法
每个具体命令者都实现 命令者接口,并依赖一个 接收者对象, 命令的执行代理给接收者来执行
调用者类,依赖一个命令者接口对象,由命令者接口来执行。 多态传入不同的具体命令者, 最终由接收者采取不同的执行方式
示例 (原来的实现)
比如,有一些文件操作命令:open, close, save, delete,接收者为一个编辑器editor那,首先,需要定义一个命令接口:IAction
public interface IAction {//原 命令者 抽象出一个 执行命令的方法 void perform(); }
再定义四个具体命令者类OpenAction、CloseAction、SaveAction、DeleteAction。
CloseAction代码:
public class CloseAction implements IAction { private Editor mEditor; public CloseAction(Editor editor) { this.mEditor = editor; } @Override public void perform() { this.mEditor.close(); } }
其他三个实现与CloseAction类似。
Editor类(接收者),就定义了收到四个命令的各个具体实现:
public class Editor { public void save() { System.out.println("save"); } public void delete() { System.out.println("delete"); } public void open() { System.out.println("open"); } public void close() { System.out.println("close"); } }
注:如果说不同的编辑器对这些命令都有各自不同的实现,那么也可以定义一个IEditor接口,再实现不同的Editor。关于此点就不详细讨论了
最后还要有一个调用者,可以是一个类:
public class Invoker { private IAction action; public Invoker(IAction action) { this.action = action; } public void invoke() { this.action.perform(); } }
client发起命令:
Editor editor = new Editor(); new Invoker(new OpenAction(editor)).invoke(); new Invoker(new CloseAction(editor)).invoke(); new Invoker(new SaveAction(editor)).invoke(); new Invoker(new DeleteAction(editor)).invoke();
这里的调用者,可以不使用类的方式定义,而是定义成client中的一个方法:
private void invoke(IAction action) { action.perform(); }
client发起命令调用:
invoke(new OpenAction(editor)); invoke(new CloseAction(editor)); invoke(new SaveAction(editor)); invoke(new DeleteAction(editor));
Lambda expression 简化版
保留IAction、Editor和 client中的invoke(Iaction action)。client发起命令调用:
Editor editor = new Editor(); invoke(() -> editor.open()); invoke(() -> editor.close()); invoke(() -> editor.save()); invoke(() -> editor.delete());
这样,使用Lambda expression后,就省略了具体命令者类的定义。并能一目了然地看到最终执行的是哪个方法。
不用担心这样书写后,会破坏原本命令者模式的 请求与执行分离 的作用。
因 invoke(() -> editor.open()); <==>
invoke(new IAction() { @Override public void perform() { editor.open(); } });
如果保留调用类Invoker,那就类似如下调用:
new Invoker(() -> editor.open()).invoke();
相关文章推荐
- Android Studio使用gradle-retrolambda支持Java8 新特性 Lambde表达式
- 使用Java5特性来简化反射编程
- android 2.3 StrictMode 使用 Android 2.3新特性StrictMode限制模式的工作方式
- Android开发使用Java8新特性
- Android 使用Java8新特性之"方法引用"
- 使用Java5特性来简化反射编程
- 使用Java5特性来简化反射编程
- Java(Android)编程思想笔记03:在Android开发中使用MVP模式
- Android开发使用Java8新特性
- [Android测试] AS+Appium+Java+Win 自动化测试之八:使用PageObject模式和重封装
- android中使用java8新特性lambda表达式
- Android歌词秀设计思路(6)运用Proxy设计模式简化歌词播放服务的使用
- 利用Lambda表达式简化命令者模式
- Android开发使用Java8新特性
- 在 Android 中使用 Java8 的特性
- 使用template method模式简化android列表页面
- 在Android中使用Java 8的lambda表达式
- android上的JAVA8:使用retrolambda
- Android 系列 2.11使用Java 8 java.time API简化日期/时间计算
- 在Android项目中启用Java 8的部分特性--Lambda & Method References