Retrolambda Use Lambdas in Android
kojilin@Cubie Inc.2015/1/28
input.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { }});
input.setOnClickListener(v -> { ...});
Lambda Syntax
(int x, int y) -> x + y
(int x, int y) -> x + yArgument List
(int x, int y) -> x + yArrow Token
(int x, int y) -> x + yBody
(int x, int y) -> x + y
() -> 42
(String s) -> { System.out.println(s); }
● Body is expression
● Body is statement block
input.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { }});
input.setOnClickListener(v -> { ...});
input.setOnClickListener(v -> ...);
為何開心?• 各種用到 anonymous class 的狀況
• Event listener• Runnable• RxJava• Future / Promise Pattern API
input.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { }});
input.setOnClickListener(v -> { ...});
handler.post(new Runnable() { @Override public void run() { ... }});
handler.post(() -> { ...});
Observable.from(new Integer[] {...}) .filter(new Func1<Integer, Boolean>() { @Override public Boolean call(Integer v) { return v < 4; }}).subscribe(new Action1<Integer>() { @Override public void call(Integer value) { System.out.println("Value: " + value); }});
Observable.from(new Integer[] {...}) .filter(v -> v < 4) .subscribe(value -> { System.out.println("Value: " + value); });
build.gradle
buildscript { ... dependencies { classpath 'me.tatarka:gradle-retrolambda:2.5.0' }}...apply plugin: 'me.tatarka.retrolambda'...
• ProGuard
• -dontwarn java.lang.invoke.**
• 而且 IDE Debug feature 也沒問題
好像很不錯,馬上導入 !?
等一下!!!
Java source(.java)
Java bytecode(.class)
Dalvik bytecode(.dex)
Java source(.java)
Java bytecode(.class)
Dalvik bytecode(.dex)
Java 8 bytecode Java 5/6/7 bytecode
• 未來 JDK 編譯出的 bytecode 改變
• 需等 retrolambda 支援
• 不支援的話,就得持續使用舊版 JDK
• Android 新的編譯過程不經過 bytecode
• Jack & Jill
• 新增修改程式碼有時會有 NoClassDefFoundError
• 未來 Android 上的 Java 語法應該(!?)會有 Java 8,所
以程式碼切換過去也不用改變
List<Integer> list = Arrays.asList(1,2,3);Integer sum = list.stream() .map(i -> i * 2) .reduce(0, (x, y) -> x + y);
List<Integer> list = Arrays.asList(1,2,3);Integer sum = list.stream() .map(i -> i * 2) .reduce(0, (x, y) -> x + y);
等一下!!!
• 因為是支援 lambda 語法,所以 java 8 的 API 並
沒有支援
• 可以使用 Guava, FunctionalJava 類的專案
Integer sum = fj.data.List.list(1,2,3) .map(i -> i * 2) .foldLeft(i -> (j -> i + j), 0);
除了 lambda 外其他好處
• Method reference
• Effective Final
• Generalized Target-Type Inference
input.setOnClickListener(System.out::println);