<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          聲明式 UI?Android 官方怒推的 Jetpack Compose 到底是什么

          共 4053字,需瀏覽 9分鐘

           ·

          2021-03-04 11:45


          視頻先行

          下面是視頻內(nèi)容的腳本整理稿。如果你看了視頻,那下面的文稿就不用看了,直接翻到底部就行。

          開始

          聲明式 UI;更簡單的自定義;實時的、帶交互的預(yù)覽功能;還有更強的性能和功能。這就是 Android 官方全新推出的 UI 框架——Jetpack Compose。

          大家好,我是扔物線朱凱。

          2019 年中,Google 在 I/O 大會上公布了 Android 最新的 UI 框架:Jetpack Compose。Compose 可以說是 Android 官方有史以來動作最大的一個庫了。它在 2019 年中就公布了,但要到今年也就是 2021 年才會正式發(fā)布。這兩年的時間 Android 團隊在干嘛?在開發(fā)這個庫,在開發(fā) Compose。一個 UI 框架而已,為什么要花兩年來打造呢?因為 Compose 并不是像 RecyclerView、ConstraintLayout 這種做了一個或者幾個高級的 UI 控件,而是直接拋棄了我們寫了 N 年的 ViewViewGroup 那一套東西,從上到下擼了一整套全新的 UI 框架。直白點說就是,它的渲染機制、布局機制、觸摸算法以及 UI 的具體寫法,全都是新的。

          Compose 的寫法

          Compose 從一出現(xiàn),最受到官方推崇以及關(guān)注者贊揚的就是它實現(xiàn)了聲明式 UI,說它比我們傳統(tǒng)寫法的「命令式 UI」怎么怎么好——我們傳統(tǒng)的 ViewViewGroup 那一套系統(tǒng)的寫法叫「命令式」。但是對于大多數(shù) Android 開發(fā)者來說,我們的第一個問題就是:什么是「聲明式 UI」?

          在講「聲明式 UI」之前,我們先看一下 Compose 的代碼長什么樣。Compose 是用 Kotlin 來寫的,它的每個控件都是一個函數(shù)調(diào)用。比如你要顯示一塊文字,你就這么寫:

          Text("Hello")

          看起來好像只是調(diào)用構(gòu)造函數(shù)創(chuàng)建了一個對象,但這么寫就已經(jīng)可以顯示出一塊文字來了。

          另外——這其實也并沒有創(chuàng)建對象,這個?Text()?也不是一個構(gòu)造函數(shù),而是一個普通函數(shù)。

          Text("Hello")

          ...

          @Composable
          fun?Text(...)?{
          ????...
          }

          普通函數(shù)用大寫開頭干嘛?很簡單,為了辨識度。Compose 規(guī)定了這種大寫開頭的命名方式,這樣我們就能一眼認出來:哦,這是個 Compose 的函數(shù)——或者用更官方的叫法:這是一個 Composable。

          到這兒有人可能就會想:這個 Text() 它實質(zhì)上是個什么?是個 TextView 嗎?不是的。剛才我說過一次,Compose 的渲染機制、布局機制、觸摸機制全都是新寫的,所以這個 Text() 的底層不是 TextView,也不是任何一個原生控件,而是直接調(diào)用了更下層的繪制 API,也就是 Canvas 那一套東西。同理,Compose 里的各個組件,都是獨立的新實現(xiàn)。

          好繼續(xù)說。一個函數(shù)調(diào)用是一個組件;兩個函數(shù)調(diào)用就是兩個組件;

          Text("Hello")
          Image()

          多個函數(shù)組合起來,就是一個完整的界面:

          Column?{
          ????Text("Hello")
          ????Image()
          }

          這,就是 Compose 的寫法??赐晁膶懛ǎ覀兙涂梢曰氐絼偛诺膯栴}:什么是「聲明式 UI」?這段代碼怎么就「聲明式」了?它和我們一直以來的寫法有什么區(qū)別?

          首先,我們一般怎么寫 UI 的?xml 文件,對吧?比如這個界面,上下排列的一塊文字和一個圖片,它的等價傳統(tǒng)寫法是這樣的:

          <!--?代碼經(jīng)過一定簡化?-->
          <LinearLayout>
          ??<TextView?android:text="Hello"?/>
          ??<ImageView?/>
          </LinearLayout>

          一個 LinearLayout,里面包著一個 TextView 和一個 ImageView。

          看了以后什么感覺?大同小異是吧?除了名字換換、格式變變,大體上是一樣的。對吧?

          那為什么左邊就叫命令式,右邊就叫聲明式呢?xml 命令誰了?以及,右邊這寫法怎么就更優(yōu)秀了?我為什么要學一個看起來并沒有什么本質(zhì)區(qū)別的新寫法來為難自己?

          其實所謂「聲明式 UI」,指的是你只需要把界面給「聲明」出來,而不需要手動更新。關(guān)鍵在于「不需要手動更新」。比如左邊這個布局里的 TextView,如果它對應(yīng)的數(shù)據(jù)改變了,我要怎么把新的文字更新到它?很簡單:findViewById()、setText() 對吧?

          findViewById()
          setText()

          而如果用 Compose 呢?怎么更新?不用更新。因為 Compose 的界面會隨著數(shù)據(jù)自動更新。

          Compose 會對界面中用到的數(shù)據(jù)自動進行訂閱——不管是字符串還是圖像還是別的什么,Compose 全部能夠自動訂閱——這樣當數(shù)據(jù)改變的時候,Compose 會直接把新的數(shù)據(jù)更新到界面。

          var?text?=?"Hello"

          ...

          Column?{
          ????Text(text)
          ????Image()
          }

          這個「自動訂閱」的功能很容易使用,你只要在初始化的時候加上一個?by mutableStateOf()?,剩下的全都由 Compose 自動搞定。

          var?text?by?mutableStateOf("Hello")

          ...

          Column?{
          ????Text(text)
          ????Image()
          }

          這個神奇的功能是利用 Kotlin 的 Property Delegation 屬性委托來實現(xiàn)的。這也在一定程度上回答了一個問題:?為什么 Compose 只能用 Kotlin 寫,而不能用 Java?因為它用了大量的 Kotlin 特性,而這些特性用 Java 不能簡單實現(xiàn)。注意,雖然 Kotlin 和 Java 是兼容的,Kotlin 能做到的事 Java 也能做到,但是有些東西它「不能簡單實現(xiàn)」就約等于不能實現(xiàn)了,因為不實用啊!對吧?所以 Android 自稱永遠不放棄對 Java 的支持,他們就這么一說,你就這么一聽,不要真的就不學 Kotlin,不然會越來越難受。你看這 Compose 不是已經(jīng)在逼著我們用 Kotlin 了嗎?

          好拐回來,這就是所謂的「聲明式 UI」:你只要聲明界面是什么樣子,不用手動去更新,因為界面會自動更新。而傳統(tǒng)的寫法里,數(shù)據(jù)發(fā)生了改變,我們得手動用 Java 代碼或者 Kotlin 代碼去把新數(shù)據(jù)更新到界面。你給出詳細的步驟,去命令界面進行更新,這就是所謂的「命令式 UI」。

          那么現(xiàn)在我們再往回拐:傳統(tǒng)的 xml 寫法和 Compose 的 Kotlin 寫法,為什么一個是「命令式」,一個是「聲明式」?這個問題其實本身就是錯的。單單一段 xml 代碼并不能稱作是命令式 UI。傳統(tǒng)寫法的「命令式」并不在于 xml 部分,而在于 Java 部分:Java 代碼去指揮、去命令界面更新,這才是「命令式」的含義所在;而 Compose 通過訂閱機制來自動更新,所以不需要做這種「命令」,所以是「聲明式」。

          所以你看,不管是聲明式還是命令式,跟 xml 和 Kotlin 是無關(guān)的,它們并不是語言角度的定義,也不是寫法角度的定義,而是——功能角度。一個 UI 框架,如果可以讓開發(fā)者只聲明出界面的樣子,而不用去寫各種界面更新的代碼,它就是一個聲明式的 UI 框架。換句話說,如果 Android 可以讓我們用 xml 寫的界面也和數(shù)據(jù)做關(guān)聯(lián),讓界面自動更新而不需要開發(fā)者手寫更新代碼,那么它就也是聲明式 UI。聲明式 UI 是一種強大的功能,而不是一種優(yōu)秀的代碼風格。

          哎?數(shù)據(jù)和界面做關(guān)聯(lián),界面跟著數(shù)據(jù)自動更新,這不就是數(shù)據(jù)綁定嗎?Android 已經(jīng)有這樣的官方庫了??!就叫 Data Binding,是吧?我用它不就得了,為什么要費這么大勁去用 Compose 呢?

          首先,對!Data Binding 和 Compose 本質(zhì)上都是通過界面對數(shù)據(jù)進行訂閱來實現(xiàn)了界面的自動更新,但!它們是有關(guān)鍵區(qū)別的。區(qū)別就在于,Data Binding 通過數(shù)據(jù)更新的只能是界面元素的值,而 Compose 可以更新界面中的任何內(nèi)容,包括界面的結(jié)構(gòu)。比如你用一個 Boolean 類型的變量控制界面中某個元素是否顯示,

          var?text?=?...
          var?showImage?=?...
          Column?{
          ????Text(text)
          ????if?(showImage)?{
          ????????Image()
          ????}
          }

          當你把變量的值從 true 變成 false 的時候,

          var?text?=?...
          var?showImage?=?...
          Column?{
          ????Text(text)
          ????if?(showImage)?{
          ????????Image()
          ????}
          }

          ...

          showImage?=?false

          這個元素會從界面中完全消失,就像從來沒有出現(xiàn)過一樣,而不是用 setVisibility(GONE) 這種方式從視覺上隱藏。這兩種策略看起來好像區(qū)別不大,那是因為我舉的例子簡單,實際上這是一種機制的改變,而這種機制的改變給界面開發(fā)帶來的靈活性和性能的提升是非常大的。你想一下,是不是?

          總結(jié)

          所以「聲明式 UI」還真的不是個噱頭,它讓 Compose 比傳統(tǒng)的 UI 系統(tǒng)強大得多。而且現(xiàn)在除了 Android 的 Compose 之外,iOS 的 SwiftUI 以及跨平臺的 Flutter 也都是聲明式的。聲明式 UI 已經(jīng)是一種趨勢了。

          當然了不管怎么說,客觀地講,Compose 確實是一套比較難學的東西,因為它畢竟太新也太大了,它是一個完整的、全新的框架,確實讓很多人感覺「學不動」,這也是個事實。那怎么辦呢?學不動怎么辦呢?

          我的建議是——

          學。

          瀏覽 175
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美性爱网站免费 | 在线播放亚洲高清 | 毛片A片中文字幕在线视频 | 91在线无码精品秘 豆花 | 亚洲色吧色婷婷 |