Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android tips(十三)--)Android開發過程中使用Lambda表達式

Android tips(十三)--)Android開發過程中使用Lambda表達式

編輯:關於Android編程

新的Java8 API中提供了不少新的特性,其中就有Lambda表達式。而本文我們將主要介紹一下在Android開發過程中如何使用Lambda表達式,這裡主要是為我們後續介紹RxAndroid、RxJava相關知識做鋪墊的。

Lambda表達式的概念

Lambda表達式是Java8中提供的一種新的特性,它支持Java也能進行簡單的“函數式編程”,即Lambda允許你通過表達式來代替功能接口。其實Lambda表達式的本質只是一個”語法糖”,由編譯器推斷並幫你轉換包裝為常規的代碼,因此你可以使用更少的代碼來實現同樣的功能。

Lambda表達式就和方法一樣,它提供了一個正常的參數列表和一個使用這些參數的主體(body,可以是一個表達式或一個代碼塊)

咋樣很厲害吧?下面我們將慢慢看一下Lambda表達式的相關知識。

標准的Lambda表達式寫法

那麼Lambda表達式具體如何編寫呢?下面我們可以看一個具體的Lambda表達式實例。

(int x, int y) -> {
    Log.i("TAG", "x:" + x + "  y:" + y);
    return x + y;
}

這是一個標准的Lambda表達式的寫法,一個Lambda表達式通常有三部分組成:

參數:(int a, int b)是這個lambda expression的參數部分,包括參數類型和參數名

箭頭:->

代碼塊:就是用”{}”包含著的那兩句代碼。

其中由於參數的類型是可以通過系統上下文推斷出來的,所以在很多情況下,參數的類型是可以省略的,可以省略的寫成:

(x, y) -> {
    Log.i("TAG", "x:" + x + "  y:" + y);
    return x + y;
}

其實不光參數類型是可以省略的,代碼塊也是可以省略的,比如如果我們的代碼塊中只有一句代碼,我們可以寫成:

(x, y) -> 
    return x + y;

也可以寫成:

(x, y) -> return x + y

而這個時候其實return關鍵字也是可以省略的,這時候我們就可以這樣寫:

(x, y) -> x + y

好精簡有木有…

Lambda表達式的幾個特性

(1)類型推導
編譯器負責推導Lambda表達式的類型。它利用Lambda表達式所在上下文所期待的類型進行推導, 這個被期待的類型被稱為目標類型。就是說我們傳入的參數可以無需寫類型了!

(2)變量捕獲
對於lambda表達式和內部類, 我們允許在其中捕獲那些符合有效只讀(Effectively final)的局部變量。簡單的說,如果一個局部變量在初始化後從未被修改過,那麼它就符合有效只讀的要求, 換句話說,加上final後也不會導致編譯錯誤的局部變量就是有效只讀變量

(3)方法引用
如果我們想要調用的方法擁有一個名字,我們就可以通過它的名字直接調用它:

Comparator byName = Comparator.comparing(Person::getName); 

此處無需再傳入參數,Lambda會自動裝配成Person類型進來然後執行getName()方法,而後返回getName()的String

方法引用有很多種,它們的語法如下:

靜態方法引用:ClassName::methodName
實例上的實例方法引用:instanceReference::methodName
超類上的實例方法引用:super::methodName
類型上的實例方法引用:ClassName::methodName
構造方法引用:Class::new
數組構造方法引用:TypeName[]::new

學習使用Lambda表達式
/**
 * 定義線程測試例子
 */
public static void m1() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                Log.i("TAG", "定義一個簡單測試例子...");
            }
        }).start();
    }

以上是我們使用的普通的Java代碼實現的一個簡單的線程例子,那麼如果使用Lambda表達式是什麼形式的呢?

/**
 * 使用Lambda表達式實現
 */
public static void m2() {
        new Thread(
                () -> {
                    Log.i("TAG", "使用Lambda表達式的例子...");
                }
        ).start();
    }

可以看到通過Lambda表達式代碼還是相當簡潔的

(1)我們直接在編輯器裡面寫Lambda表達式是會報錯的,因為Lambda不可以這樣使用。在關於Lambda的使用其實需要跟一個叫做函數接口(Functional Interface)的東西綁定在一起。什麼是函數接口呢?函數接口是在Java8 中引入的概念,其就是為了Lambda表達式而引入的。我們知道Java中的接口的概念,而函數接口其實就是:

一個只定義了一個抽象方法的接口

比如ClickListener這個接口就只有一個onClick方法,那麼它就是一個函數接口。在Android開發過程中我們經常會這樣使用OnClickListener:

/**
 * 定義OnClickListener,處理按鈕點擊事件
 */
View.OnClickListener onClickListener = newView.OnClickListener() {    
    @Override
    public void onClick(View view) {
        // 處理按鈕點擊事件
        doSomeThing();
    }
});
findViewById(R.id.titleView).setOnClickListener(onClickListener);

其實我們除了上面定義的OnClickListener我們也可以直接使用匿名內部類:

/**
 * 定義匿名內部類處理組件的點擊事件
 */
findViewById(R.id.titleView).setOnClickListener(new View.OnClickListener() {    
    @Override
    public void onClick(View view) {
        // 處理組件的點擊事件
        doSomeThing();
    }
});

在上面的代碼中,我們可以發現其實我們主要是調用其他的doSomeThing()方法,該方法中實現了我們的按鈕點擊事件,並且這裡我們通過一系列的縮進,括號來實現了這個調用操作,有木有覺得很繁瑣?在Java 8出現之前,在代碼中經常有這樣的實現。現在好了,有了Lambda達表示,我們可以這樣寫了:

/**
 * 自定義OnClickListener按鈕點擊事件
 */
View.OnClickListener onClickListener = view -> doSomeThing();
findViewById(R.id.titleView).setOnClickListener(onClickListener);

至於匿名內部類我們也可以這樣寫:

findViewById(R.id.titleView).setOnClickListener(view -> doSomeThing());

通過使用Lambda表達式之後代碼就變得相當簡潔了。從上面的例子可以看到,Lambda表達式簡化了函數接口的實例的創建,可以在代碼層次簡化函數接口,內部匿名類的寫法等。

Lambda表達式的優缺點

上面我們簡單的介紹了Lambda表達式的概念,寫法與特性等,那麼它具體有什麼優缺點呢?

優點:

使用Lambda表達式可以極大的簡化代碼。去除了很多無用的Java代碼,使得代碼更為簡潔明了;

缺點:

可讀性差。在代碼簡潔的情況下,另一方面又讓大多程序員很難讀懂。因為很少程序員接觸使用它。

如何在Android Studio中使用Lambda表達式

Android Studio默認使用Lambda表達式是會報錯的,即使你使用的是Java 8,升級Android Studio的Language level為1.8

  

這裡寫圖片描述

如果是非Java8,那麼我們如何使用Lambda表達式呢?

幸好有Lambda的gradle插件gradle-retrolambda,通過這個插件我們可以在Android Studio中使用Lambda表達式了,其可以兼容到Java5。

至於具體的使用方式我們可以參考其Github地址:gradle-retrolambda

具體如:

/**
 * 自定義組件點擊事件
 */
imageView.setOnClickListener { view ->
            Log.i("TAG", "按鈕點擊事件...")
        }

總結:

相對來說使用Lambda表達式還是能夠優化一些代碼的,但是相應的代碼的可能性會有相應的下降,在實際的開發過程中可根據具體的情況作出相應的選擇。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved