日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ButterKnife被弃用,ViewBinding才是findView的未来?

發布時間:2023/12/16 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ButterKnife被弃用,ViewBinding才是findView的未来? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最近Android Studio更新到了4.1版本,發現項目中使用ButterKnife注解id的代碼出現了警告,警告信息如下:

Resource IDs will be non-final in Android Gradle Plugin version 5.0, avoid using them as annotation attributes

從警告信息中可以看到在Gradle 5.0的插件中Resource 的Id值將不會再是final類型,因此應該避免在注解屬性中使用Id。這意味著當我們把Gradle插件升級到5.0版本之后ButterKnife將無法再被使用!同時,我們在ButterKnife的官方文檔上也看到了ButterKnife被標注棄用的信息:

陪伴我們多年,曾經輝煌一時,不可一世的ButterKnife也要壽終正寢,即將迎來它生命的終點。借這個機會,我們不妨來回顧一下Android開發中findView的發展史,以及展望下findView的未來。

一、Android綁定View的發展史

從Android系統誕生至今,在代碼中findView一直是Android開發者無法繞開的一道程序。從最初的findViewbyId到如今炙手可熱的ViewBinding,期間涌現出了許多findView的方式,它們讓findView變得更加簡單,也讓我們的代碼變得更加簡潔。但隨著Android新技術的發展,這些findView的方法也正在被一個一個的拋棄。本節內容我們就來回顧一下Android開發中findView的發展史。

1.findViewById

findViewById是Android開發中最原始,也是最基礎的一種獲取View的方法。它由Google官方提供,在Android開發生態的早期也是唯一一種能夠獲取View的方式。雖然它使用簡單且根正苗紅,貫穿古今。但由于高度重復的代碼結構深受開發者詬病。在一個復雜布局的頁面僅僅是findViewById的代碼往往就能達到數十行。開發者無時無刻不想著棄用這一方案,因此后續衍生出了多種獲取View的方式來簡化代碼。但萬變不離其宗,歸根結底,這些方式最終都還是通過findViewById來實現的。雖然它是最不被開發者認可的一種的方式,但時至今日開發者也無法擺脫它籠罩著的陰影。一臉你看不慣我你打我呀的表情!

2.ButterKnife

就在大家都在唾棄findViewById的大量重復代碼時,一個插件橫空出世。它通過一個BindView注解,傳入一個Resource Id就能輕松獲取到Id對應的View。代碼如下:

public class MainActivity extends AppCompatActivity {@BindView(R.id.text_view)TextView mTextView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ButterKnife.bind(this);}}

它就是紅極一時,時至今日大家依然還在用著的ButterKnife。ButterKnife通過最前沿的Java技術(最初的版本可能是反射,未加考究)–Java編譯時注解處理器,在編譯時自動生成findViewById的代碼。例如,上邊的例子通過ButterKnife會生成一個MainActivity_ViewBinding 類,在這個類中通過findViewById為mTextView賦值,其代碼如下:

public class MainActivity_ViewBinding implements Unbinder {private MainActivity target;@UiThreadpublic MainActivity_ViewBinding(MainActivity target) {this(target, target.getWindow().getDecorView());}@UiThreadpublic MainActivity_ViewBinding(MainActivity target, View source) {this.target = target;target.mTextView = Utils.findRequiredViewAsType(source, R.id.text_view, "field 'mTextView'", TextView.class);}@Override@CallSuperpublic void unbind() {MainActivity target = this.target;if (target == null) throw new IllegalStateException("Bindings already cleare");this.target = null;target.mTextView = null;} }

這一操作省去了開發者手動編寫findViewById的時間,大大簡化了代碼,同時提高了開發效率。在當時的開發者看來ButterKnife不得不說是一個神器,以至于到后來成了Android項目開發的標配。

后來,隨著Android Studio的誕生,Eclipse開發Android項目逐漸淡出歷史舞臺。Android studio的出現,帶來了全新的技術,模塊化風靡一時。大概在這個時候,Google官方似乎就已經有了改造R類的想法。在Android項目的library模塊中,生成R類中的成員變量就已經改為了非final修飾。同時,Google官方也不再建議在app模塊的代碼中使用像:switch(view.getId())這樣的代碼。

正如Android studio官網文檔《Non-constant Fields in Case Labels》上給出的原因:

In other words, the constants are not final in a library project. The reason for this is simple: When multiple library projects are combined, the actual values of the fields (which must be unique) could collide. Before ADT 14, all fields were final, so as a result, all libraries had to have all their resources and associated Java code recompiled along with the main project whenever they were used. This was bad for performance, since it made builds very slow. It also prevented distributing library projects that didn’t include the source code, limiting the usage scope of library projects.

這一改變直接致使ButterKnife無法在Android項目的library模塊中使用。而此時,ButterKnife正是如日中天,追隨的開發者不計其數。為了能夠讓ButterKnife運行在library模塊,ButterKnife的作者Jake Wharton大佬曲線救國,通過生成R2類讓ButterKnife在library模塊中復活,并且得以發展壯大。但不得不說,此時的ButterKnife就已經埋下了深深的隱患,并導致了其最終的潰敗。

3.DataBinding

DataBinding是Google官方在2015年谷歌I/O大會上發布的一個數據綁定框架,它并非專為findView而生,而是作為MVVM架構的雙向綁定數據的工具。findView的功能僅僅是DataBinding的一個附贈品。

開發者一般會在MVVM架構的項目中使用DataBinding來獲取View。但是它也有很多詬病,比如需要修改xml的結構,在xml外部嵌套一個標簽。并且很多情況下需要手動build才能生成DataBinding相關類。諸如此類問題,自然不會得到開發者的青睞。

關于DataBinding的詳細使用在這里不做探討。

4.Kotlin Android Extensions

2017年Google I/O開發者大會中,Google宣布Kotlin成為Android開發的一級語言,自此,Kotlin “轉正”與Java并駕齊驅。而JetBrain推出的Kotlin Android Extension(以下簡稱KAE)插件成為了有史以來最簡單的獲取View的方法,簡單到無需任何代碼,直接通過id作為View使用。這一功能足以讓所有Android開發者抓狂,紛紛感嘆這才是findView的未來啊,終于可以和裹挾開發者十多年的findViewById說拜拜了!
作為一個Android開發者,不知道你是否會好奇Kotlin是如何將Id作為View的?我們不妨寫一個簡單的例子:

class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)textView.text = "Test"} }

布局文件中TextView的id設置為“textView”,則在Activity中可以直接將textView作為一個TextView來使用。我們通過Android Studio的工具將kotlin的字節碼反編譯成Java代碼看下

通過上述操作,打開kotlin的字節碼后,再通過Decompile反編譯成Java代碼,則會得到如下圖所示的結果:

通過反編譯得到的Java代碼我們發現Kotlin的這一操作其實也是通過findViewById實現的。只是通過插件的方式讓我們感覺上是用了View的Id。

通過Kotlin的擴展插件來find view,無疑是一種優秀的方案。但這一方案并不是無懈可擊。它存在以下幾個缺點:

  • 類型安全:res下的任何id都可以被訪問,有可能因訪問了非當前Layout下的id而出錯
  • 空安全:這主要體現在Configuration中的對應布局不全時,運行時可能出現NPE
  • 兼容性:只能在kotlin中使用,java不友好
  • 局限性:不能跨module使用

也正是這幾個缺點導致了KAE的大潰敗。隨著Google對親兒子ViewBinding的大力推廣,KAE最終也招架不住,只能繳械投降—Jetbrains在官網宣布廢棄KAE,并推薦開發者使用ViewBinding.

5.ViewBinding

到這里,以上提到的多種findView方案都已經被廢棄,唯獨只剩Google官方正在大力推廣的ViewBinding組件。ViewBinding是Google在2019年I/O大會上公布的一款Android視圖綁定工具。它的使用方式有點類似DataBinding,但相比DataBinding,ViewBinding是一個更輕量級、更純粹的findViewById的替代方案。它具有以下幾個優點:

  • 類型安全: ViewBinding會基于布局中的View生成類型正確的屬性。比如,在布局中放入了一個 TextView ,視圖綁定就會暴露出一個 TextView 類型的屬性供開發中使用。
  • 空安全:ViewBinding會檢測某個視圖是不是只在一些配置下存在,并依據結果生成帶有 @Nullable 注解的屬性。所以即使在多種配置下定義的布局文件,視圖綁定依然能夠保證空安全。
  • ViewBinding生成的綁定類是一個Java類,并且添加了Kotlin的注解,可以很好的支持 Java 和 Kotlin 兩種編程語言。

同時,Google官方還給出了一個ViewBinding、ButterKnife以及KAE的對比,如下圖:

總而言之,到目前為止除了ViewBinding我們已經別無選擇。那么不妨接下來詳細探究下ViewBinding的使用方法。

二、ViewBinding使用詳解

1.開啟ViewBinding

Android Studio對于ViewBinding的支持是從3.6版本開始的,AS 3.6版本內置了Gradle插件。只需要在build.gradle中通過以下配置即可開啟ViewBinding:

android {buildFeatures {viewBinding = true} }

如果,你的項目存在多個模塊,則需要在每個模塊的gradle中添加上述配置。完成以上配置后ViewBinding會為所有布局文件自動生成對應的綁定類。且無須修改原有布局的 XML 文件,ViewBinding會根據現有的布局自動完成所有工作。

2.在Activity中使用ViewBinding

首先編寫activity_main.xml的布局文件,如下:

<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><TextViewandroid:id="@+id/text_view"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Hello World!"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent" /></androidx.constraintlayout.widget.ConstraintLayout>

完成后gradle插件會自動生成一個名為ActivityMainBinding的Java類,在Activity中通過ActivityMainBinding獲取Binding實例,如下:

override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)val binding = ActivityMainBinding.inflate(layoutInflater)setContentView(binding.root)binding.textView.text = "Hello World"}

3.ViewBinding與include標簽

在項目開發中,通常我們會使用include標簽來簡化布局文件,那么在使用了include標簽的布局文件中,應該如何使用ViewBinding呢?且看代碼:

// activity_main.xml <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><includeandroid:id="@+id/include"layout="@layout/layout_include" /></androidx.constraintlayout.widget.ConstraintLayout>// layout_include.xml <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"><TextViewandroid:id="@+id/tv_text"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Hello World!"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent" /></androidx.constraintlayout.widget.ConstraintLayout>

上述兩個布局文件會分別生成ActivityMainBinding與LayoutIncludeBinding兩個Java類,并且ActivityMainBinding類中通過組合依賴了LayoutIncludeBinding類。因此,使用方式如下:

override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)val binding = ActivityMainBinding.inflate(layoutInflater)setContentView(binding.root)// 從ActivityMainBinding中獲取LayoutIncludeBindingval include = binding.include// 通過LayoutIncludeBinding為TextView賦值include.tvText.text = "Hello World"}

如果layout_include.xml文件位于子模塊,經實踐與以上代碼的使用方式并無任何差異,但一定要在子模塊中開啟ViewBinding才行。

4.ViewBinding在Fragment中的使用
在Fragment中使用ViewBinding與Activity中有些差異,這里為了簡便,我們使用上述中的activity_main.xml作為Fragment的布局文件,則Fragment的代碼如下:

private lateinit var binding: ActivityMainBindingoverride fun onCreateView(inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?): View? {binding = ActivityMainBinding.inflate(inflater, container, false)return binding.root}override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)binding.textView.text="Hello World"}

5.ViewBinding在RecyclerView#Adapter中的使用

布局文件不再貼出,直接看Adapter的代碼,如下所示:

class TestAdapter : RecyclerView.Adapter<TestViewHolder>() {override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TestViewHolder {val binding =ItemTestBinding.inflate(LayoutInflater.from(parent.context))return TestViewHolder(binding)}override fun onBindViewHolder(holder: TestViewHolder, position: Int) {holder.binding.textView.text = "Hello World"}override fun getItemCount(): Int {return 10}class TestViewHolder(var binding: ItemTestBinding) :RecyclerView.ViewHolder(binding.root) }

通過以上幾個實例可以看到ViewBinding的使用是非常簡單的。而ViewBinding的實現原理也并不難,Gradle插件會根據布局文件在項目的build目錄下生成相應的ViewBinding類,并且,最終也是通過findViewById來完成View的獲取的。具體實現代碼不再貼出,感興趣的同學可以自行查看。

三、展望與總結

時代在發展,Android獲取View的方式仍在變化。ViewBinding無疑是一個優秀的組件,但它真的是Android開發中獲取View的最優方案嗎?顯然,并不是!因為ViewBinding歸根結底還是通過findViewById實現,且需要插件生成相關的Binding類,雖然省去了手動編寫,但是ViewBinding仍然沒能解決代碼冗余的問題。那什么才是findViewById的未來呢?大概最好的findView就是沒有findView吧!目前Google正在朝著這一方向努力,正在開發的Jetpack Compose庫就是要取代Android的布局文件,徹底消除findViewById。相信在未來某一天,隨著Jetpack Compose庫的普及,這個曠日持久的findViewById之爭也最終會畫上一個圓滿的句號。

參考&推薦閱讀

Non-constant Fields in Case Labels

The future of Kotlin Android Extensions

Kotlin Android Extensions遭廢棄,官方推薦使用ViewBinding

使用視圖綁定替代 findViewById

總結

以上是生活随笔為你收集整理的ButterKnife被弃用,ViewBinding才是findView的未来?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 黄色片视频免费观看 | 光溜溜视频素材大全美女 | 亚洲熟女乱色一区二区三区 | 国产毛片欧美毛片久久久 | 一区二区三区在线电影 | 精品一区二区三区久久 | 亚洲精品大片www | 日一日射一射 | 在线色站 | 国产剧情一区 | 天堂综合| 麻豆com| 狠狠干2021| 91成年人视频 | 国产成人a亚洲精品 | 欧美香蕉网| 欧美噜噜噜 | 亚洲Av无码成人精品区伊人 | 国产第一页在线播放 | 男人和女人日批视频 | 国产一级免费片 | 国产精品一区二区人人爽 | 丰满大乳奶做爰ⅹxx视频 | 18在线观看免费入口 | 黄色.com| 强行挺进皇后紧窄湿润小说 | 欧美精品电影一区二区 | 小珊的性放荡羞辱日记 | 日韩av一区在线观看 | 大尺度做爰呻吟舌吻情头 | 日本色呦呦| 国产欧美色图 | 免费观看一区二区三区毛片 | av影院在线| 亚洲精品免费播放 | 狠狠撸在线视频 | 天堂男人在线 | 亚洲三级在线免费观看 | 操色网 | 中文字幕欧美日韩 | 日韩高清影视在线观看 | av电影免费在线播放 | 黄色大片中文字幕 | 日日摸日日碰 | 国产黄色免费视频 | 国产精品久久久久久久久借妻 | 男女一级片 | 国产成人精品一区在线播放 | 男女洗澡互摸私密部位视频 | 青青色在线 | 久久影视精品 | 天天舔天天爽 | 国产激情二区 | 800av在线视频 | 国产成人精品电影 | 精品无码黑人又粗又大又长 | 欧美激情片一区二区 | 公交顶臀绿裙妇女配视频 | 超碰人人91 | 丰满人妻一区二区三区性色 | 自拍偷拍中文字幕 | 懂色av一区二区在线播放 | 久久综合久久网 | 轮番上阵免费观看在线电影 | 国产v片| 男人添女人下部高潮全视频 | 日韩一区二区影视 | 中文字幕中文字幕 | 欧美一级免费在线观看 | 国模无码视频一区二区三区 | 777午夜 | 91久久久久久| 成人黄色三级 | 国产美女精品 | 伊人一区二区三区 | 国产交换配乱淫视频免费 | 亚洲av片一区二区三区 | 天天插天天操天天干 | av在线电影网 | 日本十八禁视频无遮挡 | 亚州av| 91成人免费观看 | 亚洲综合黄色 | 激情片| 美腿丝袜一区二区三区 | 中国美女洗澡免费看网站 | 人妻偷人精品一区二区三区 | 国产毛片久久久久 | 99久久免费国产精精品 | 男人插入女人下面的视频 | 国产一区二区在 | 欧美日韩国产亚洲一区 | 日本大奶少妇 | 久久久久极品 | 青娱乐av在线 | 一级黄色片一级黄色片 | 日韩专区第一页 | 99这里 | 波多野结衣av电影 |