編輯:關於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
/** * 定義線程測試例子 */ 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表達式還是能夠優化一些代碼的,但是相應的代碼的可能性會有相應的下降,在實際的開發過程中可根據具體的情況作出相應的選擇。
原文地址:http://android.xsoftlab.net/training/notify-user/display-progress.html通知中包含了一個進度
在安卓中有很多種解析方式。按照大方向有xml解析和json解析。而,細致的分,xml和json解析各有自己的很多解析方式。今天這一篇主要介紹xml解析中的pull解析。對
package com.example.baidulocdemo_2;import com.baidu.location.BDLocationListener;impor
圖片效果:1 主頁代碼:MainActivity:1.首頁代碼:SyFragment:1.新聞頻道代碼:2.新聞內容代碼:跳轉——顯示新