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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

android ViewBinding

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

一、kotlin-android-extensions??????

????????在使用ViewBinding之前,我們一直使用的是kotlin-android-extensions,使用kotlin-android-extensions可以節約很多寫findViewById的時間。不過這個kotlin-android-extensions插件已經廢棄了,簡單說一下kotlin-android-extensions存在的問題:

????????1.通過反編譯kotlin-android-extensions的代碼,發現會創建一個HashMap,用來存放所有的id和對應的View的緩存,如果緩存中沒有View,那么就通過findViewById去創建并存入緩存,否則就直接獲取。所以會存在內存問題。

private HashMap _$_findViewCache;public View _$_findCachedViewById(int var1) {if (this._$_findViewCache == null) {this._$_findViewCache = new HashMap();}View var2 = (View)this._$_findViewCache.get(var1);if (var2 == null) {View var10000 = this.getView();if (var10000 == null) {return null;}var2 = var10000.findViewById(var1);this._$_findViewCache.put(var1, var2);}return var2; }public void _$_clearFindViewByIdCache() {if (this._$_findViewCache != null) {this._$_findViewCache.clear();} }// $FF: synthetic method public void onDestroyView() {super.onDestroyView();this._$_clearFindViewByIdCache(); }

????????2.由于kotlin-android-extensions是通過view的id名直接引用的,如果多個布局間的同名id,就需要手動對import進行重命名處理,如果引用錯誤的布局文件,就會出現crash。所以存在資源重名的問題。

????????3.只有Kotlin才可以使用。

????????所以ViewBinding優勢有:java,kotlin都可以使用,可以有效避免NullPointerException。

二、ViewBinding

ViewBinding使用

1.gradle配置

buildFeatures {viewBinding true }

? ????????開啟ViewBinding之后,在編譯時,AGP會自動幫我們給每個xml布局創建一個Binding類,位于build/generated/data_binding_base_class_source_out/目錄下。

public final class FragmentLoginBinding implements ViewBinding {@NonNullprivate final ConstraintLayout rootView;@NonNullpublic final ConstraintLayout container;@NonNullpublic final ProgressBar loading;@NonNullpublic final Button login;@NonNullpublic final EditText password;@NonNullpublic final EditText username;private FragmentLoginBinding(@NonNull ConstraintLayout rootView,@NonNull ConstraintLayout container, @NonNull ProgressBar loading, @NonNull Button login,@NonNull EditText password, @NonNull EditText username) {this.rootView = rootView;this.container = container;this.loading = loading;this.login = login;this.password = password;this.username = username;}@Override@NonNullpublic ConstraintLayout getRoot() {return rootView;}@NonNullpublic static FragmentLoginBinding inflate(@NonNull LayoutInflater inflater) {return inflate(inflater, null, false);}@NonNullpublic static FragmentLoginBinding inflate(@NonNull LayoutInflater inflater,@Nullable ViewGroup parent, boolean attachToParent) {View root = inflater.inflate(R.layout.fragment_login, parent, false);if (attachToParent) {parent.addView(root);}return bind(root);}@NonNullpublic static FragmentLoginBinding bind(@NonNull View rootView) {// The body of this method is generated in a way you would not otherwise write.// This is done to optimize the compiled bytecode for size and performance.int id;missingId: {ConstraintLayout container = (ConstraintLayout) rootView;id = R.id.loading;ProgressBar loading = rootView.findViewById(id);if (loading == null) {break missingId;}id = R.id.login;Button login = rootView.findViewById(id);if (login == null) {break missingId;}id = R.id.password;EditText password = rootView.findViewById(id);if (password == null) {break missingId;}id = R.id.username;EditText username = rootView.findViewById(id);if (username == null) {break missingId;}return new FragmentLoginBinding((ConstraintLayout) rootView, container, loading, login,password, username);}String missingId = rootView.getResources().getResourceName(id);throw new NullPointerException("Missing required view with ID: ".concat(missingId));} }

注意:

1.因為這些類編譯時就生成了,就不會占用運行時內存。

2.未使用的Binding文件會在混淆時被刪除,所以對包大小影響很小。

3.編譯器生成Binding文件是增量更新的。

那么如何不生成Binding類呢?tools:viewBindingIgnore="true"

<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:viewBindingIgnore="true"tools:context=".MainActivity">

2.在Activity 使用

class TestViewBindingActivity : AppCompatActivity() {private lateinit var bindding: ActivityTestViewBindingBindingoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)bindding = ActivityTestViewBindingBinding.inflate(layoutInflater)setContentView(bindding.root)changeText()}private fun changeText() {bindding.titleTv.text = "哈哈,在Activity中使用ViewBinding了"} }

<?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=".testviewbinding.TestViewBindingActivity"><TextViewandroid:id="@+id/titleTv"android:layout_width="match_parent"android:layout_height="100dp"android:gravity="center"android:text="在Activity中使用ViewBinding"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>

3.在Fragment使用

class TextViewBindingFragment : Fragment() {private var param1: String? = nullprivate var param2: String? = nullprivate var _binding: FragmentTextViewBindingBinding? = nullprivate val binding get() = _binding!!override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)arguments?.let {param1 = it.getString(ARG_PARAM1)param2 = it.getString(ARG_PARAM2)}}override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle?): View? {_binding = FragmentTextViewBindingBinding.inflate(layoutInflater, container, false)return binding.root}override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)changeText()}private fun changeText() {binding.tvTitle.text = "哈哈,在Fragment中使用ViewBinding"}override fun onDestroyView() {super.onDestroyView()_binding = null}companion object {@JvmStaticfun newInstance(param1: String, param2: String) =TextViewBindingFragment().apply {arguments = Bundle().apply {putString(ARG_PARAM1, param1)putString(ARG_PARAM2, param2)}}@JvmStaticfun newInstance() = TextViewBindingFragment()} }

class TestViewBindingActivity : AppCompatActivity() {private lateinit var bindding: ActivityTestViewBindingBindingoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)bindding = ActivityTestViewBindingBinding.inflate(layoutInflater)setContentView(bindding.root)val newInstance = TextViewBindingFragment.newInstance()addFragment(supportFragmentManager,newInstance,isAllowStateLoss = true,frameId = R.id.fragmentFrame)} }

? ? ?

<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".testviewbinding.TextViewBindingFragment"><TextViewandroid:id="@+id/tvTitle"android:layout_width="match_parent"android:layout_height="match_parent"android:text="在Fragment中" /></FrameLayout>

4.在Adapter中使用

class TestAdapterActivity : AppCompatActivity() {private lateinit var binding: ActivityTestAdapterBindingoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding = ActivityTestAdapterBinding.inflate(layoutInflater)setContentView(binding.root)initView()}companion object {val ITEMS = mutableListOf<String>("1", "2", "3", "4", "5", "6")}private fun initView() {with(binding.contentRcycler) {layoutManager = GridLayoutManager(context, 4)adapter = TestRecyclerViewAdapter(ITEMS)}} } <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".testviewbinding.TestAdapterActivity"><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/contentRcycler"android:layout_width="match_parent"android:layout_height="match_parent" /> </androidx.constraintlayout.widget.ConstraintLayout>

class TestRecyclerViewAdapter(private val values: List<String>) :RecyclerView.Adapter<TestRecyclerViewAdapter.ViewHolder>() {inner class ViewHolder(binding: RecyclerItemLayoutBinding) :RecyclerView.ViewHolder(binding.root) {val textTv = binding.contentTv}override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {return ViewHolder(RecyclerItemLayoutBinding.inflate(LayoutInflater.from(parent.context),parent,false))}override fun onBindViewHolder(holder: ViewHolder, position: Int) {val item = values[position]holder.textTv.text = item}override fun getItemCount(): Int = values.size }

<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="200dp"><TextViewandroid:id="@+id/contentTv"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:textSize="16dp"tools:text="99" /> </androidx.constraintlayout.widget.ConstraintLayout>

5.在Dialog中使用

class CommonDialog(context: Context) : Dialog(context) {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(DialogLayoutBinding.inflate(layoutInflater).root)}} <?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"android:layout_width="match_parent"android:layout_height="match_parent"><TextViewandroid:id="@+id/dialogContent"android:layout_width="200dp"android:layout_height="200dp"android:text="This is Dialog"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /></androidx.constraintlayout.widget.ConstraintLayout>

6.Include中使用

class TestIncludeActivity : AppCompatActivity() {private lateinit var binding: ActivityTestIncludeBindingoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding = ActivityTestIncludeBinding.inflate(layoutInflater)setContentView(binding.root)initView()}private fun initView() {binding.itemInclude.itemContentTv.text = "哈哈, this is include"} }<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".testviewbinding.TestIncludeActivity"><includeandroid:id="@+id/itemInclude"layout="@layout/item_layout" /> </androidx.constraintlayout.widget.ConstraintLayout>

<?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"android:layout_width="match_parent"android:layout_height="match_parent"><TextViewandroid:id="@+id/itemContentTv"android:layout_width="match_parent"android:layout_height="200dp"android:text="Test include"android:textSize="30sp"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /></androidx.constraintlayout.widget.ConstraintLayout>

三、ViewBinding封裝

1.在BaseActivity中封裝

abstract class BaseViewBindingActivity<T : ViewBinding> : AppCompatActivity() {protected val binding by lazy {getViewBinding()}override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(binding.root)}protected abstract fun getViewBinding(): T }

class ChildViewBindingMainActivity :BaseViewBindingActivity<ActivityChildViewBindingMainBinding>() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding.titleTv.text = "哈哈,this is child binding activity"}override fun getViewBinding(): ActivityChildViewBindingMainBinding {return ActivityChildViewBindingMainBinding.inflate(layoutInflater)} } <?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=".encapsulatviewbinding.ChildViewBindingMainActivity"><TextViewandroid:id="@+id/titleTv"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:text="36sp" /> </androidx.constraintlayout.widget.ConstraintLayout>

2.通過反射的方式封裝

class TestViewBindingMainActivity : AppCompatActivity() {private val binding by inflate<ActivityTestViewBindingMainBinding>()override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding.titleTv.text = "哈哈,通過反射封裝ViewBinding"} }inline fun <reified T : ViewBinding> inflateByViewBinding(layoutInflater: LayoutInflater) =T::class.java.getMethod("inflate", LayoutInflater::class.java).invoke(null, layoutInflater) as Tinline fun <reified T : ViewBinding> Activity.inflate() = lazy {inflateByViewBinding<T>(layoutInflater).apply {setContentView(root)} }

<?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=".encapsulatviewbinding.TestViewBindingMainActivity"><TextViewandroid:id="@+id/titleTv"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:textSize="36sp" /> </androidx.constraintlayout.widget.ConstraintLayout>

3.反射+基類

1.在Activity 中使用

abstract class BaseBindingMainActivity2<T : ViewBinding> : AppCompatActivity() {protected lateinit var binding: Toverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)val type = javaClass.genericSuperclassif (type is ParameterizedType) {val clazz = type.actualTypeArguments[0] as Class<T>val method = clazz.getMethod("inflate", LayoutInflater::class.java)binding = method.invoke(null, layoutInflater) as T}setContentView(binding.root)} }

class ChildViewBindingMainActivity2 :BaseBindingMainActivity2<ActivityChildViewBindingMain2Binding>() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding.titleTv.text = "哈哈,這是反射+基類的方式"} }

<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".encapsulatviewbinding.ChildViewBindingMainActivity2"><TextViewandroid:id="@+id/titleTv"android:layout_width="match_parent"android:layout_height="match_parent" /> </androidx.constraintlayout.widget.ConstraintLayout>

2.在Fragment中使用

abstract class BaseBindingViewFragment<T : ViewBinding> : Fragment() {private var _binding: T? = nullprotected val binding get() = _binding!!override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle?): View? {val type = javaClass.genericSuperclassval clazz = (type as ParameterizedType).actualTypeArguments[0] as Class<T>val method = clazz.getMethod("inflate",LayoutInflater::class.java,ViewGroup::class.java,Boolean::class.java)_binding = method.invoke(null, layoutInflater, container, false) as Tthis.viewLifecycleOwner.lifecycle.addObserver(object : LifecycleEventObserver {override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {if (event == Lifecycle.Event.ON_DESTROY) {Log.v(TAG, "onDestroy binding be null")_binding = null}}})return binding.root}companion object {const val TAG = "BaseBindingViewFragment"} }

class ChildBindingFragment : BaseBindingViewFragment<FragmentChildBindingBinding>() {override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle?): View? {return super.onCreateView(inflater, container, savedInstanceState)}companion object {@JvmStaticfun newInstance() = ChildBindingFragment()} }

class TestBindingMainActivity3 : BaseBindingMainActivity2<ActivityTestBindingMain3Binding>() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)val newInstance = ChildBindingFragment.newInstance()addFragment(supportFragmentManager,newInstance,isAllowStateLoss = true,frameId = R.id.frame)} }

<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".encapsulatviewbinding.ChildBindingFragment"><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:text="@string/hello_blank_fragment" /></FrameLayout>

4.委托的方式

class TestViewBindingFragment2 : Fragment(R.layout.fragment_test_view_binding2) {private val binding by inflate<FragmentTestViewBinding2Binding>()override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)binding.root}companion object {@JvmStaticfun newInstance() = TestViewBindingFragment2()} }inline fun <reified T : ViewBinding> Fragment.inflate() =FragmentViewBindingDelegate(T::class.java)class FragmentViewBindingDelegate<T : ViewBinding>(private val clazz: Class<T>) :ReadOnlyProperty<Fragment, T> {private var binding: T? = nulloverride fun getValue(thisRef: Fragment, property: KProperty<*>): T {if (binding == null) {binding =clazz.getMethod("bind", View::class.java).invoke(null, thisRef.requireView()) as TthisRef.viewLifecycleOwner.lifecycle.addObserver(object : LifecycleEventObserver {override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {if (event == Lifecycle.Event.ON_DESTROY) {binding = null}}})}return binding!!}}

<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".encapsulatviewbinding.TestViewBindingFragment2"><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:text="8888888" /></FrameLayout>

總結

以上是生活随笔為你收集整理的android ViewBinding的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 综合精品| 欧美 国产 日本 | 久久欧| 国产黄a三级三级三级 | 天天插天天射 | 性做久久久久久免费观看欧美 | 精品人妻一区二区免费视频 | 国产在线观看黄 | www黄色com | 激情综合网激情 | 美女爽爽爽 | 解开人妻的裙子猛烈进入 | 欧美草逼视频 | 国产探花在线观看 | 欧美三级成人 | 色呦呦在线播放 | 肥婆大荫蒂欧美另类 | 国产成人无码精品亚洲 | 天天射一射| 激情黄色av | 午夜av不卡 | 巨物撞击尤物少妇呻吟 | 午夜激情欧美 | 亚洲jizzjizz日本少妇 | 色哟哟国产精品色哟哟 | 射久久| 无码人妻精品中文字幕 | 香蕉影院在线 | 亚洲一级Av无码毛片久久精品 | 成年人黄色小视频 | 女人色极品影院 | av免费在线观看网址 | 国产成a人亚洲精v品无码 | 久久久精品视频在线观看 | 亚洲高清无码久久久 | av小次郎收藏 | 美女av一区二区 | 亚洲女人被黑人巨大进入 | 日本人dh亚洲人ⅹxx | 电影寂寞少女免费观看 | 黄色成人在线观看 | 性开放网站 | 国产女主播在线观看 | 亚洲欧美精品在线观看 | 国产真人真事毛片 | 婷婷伊人综合 | 亚洲视频精品 | 午夜激情电影在线观看 | 孕妇疯狂做爰xxxⅹ 国产精品乱码久久久久久 99久久久成人国产精品 | 久久亚洲AV无码 | 激情五月婷婷久久 | 美国毛片av | 在线视频黄 | 国产suv精品一区二区60 | 亚洲国内精品 | 91另类| 亚州成人| 日韩av在线免费看 | 成人免费看片&#39; | 女大学生的家政保姆初体验 | 91视频看 | 午夜影院免费版 | 久久不射网站 | 天堂资源站 | 中文字幕第4页 | 老熟妇仑乱一区二区视频 | gai免费观看网站外网 | 91精品国产综合久 | 国产激情av | www视频在线 | 99这里有精品视频 | 亚洲精品资源 | 亚洲网址在线 | 精品国产乱码久久久 | 国产色综合网 | 黄色xxxxx | 在线看片资源 | 99在线精品免费视频 | 黄色长视频| 性生生活大片又黄又 | 亚洲视频一二三区 | 加勒比久久综合 | 性欧美videos另类hd | 又大又粗欧美黑人aaaaa片 | 日韩黄色录像 | 免费黄色av | 久久人妻少妇嫩草av蜜桃 | 久久成人一区 | 欧美成人久久久免费播放 | 国产做受高潮 | 青青av| 黄色不卡视频 | 国产人成无码视频在线观看 | 亚洲人成电影在线播放 | 黄色三级免费网站 | 99色国产 | 国产精品视频区 | 国产麻豆一区二区三区在线观看 | 91精品国产一区二区三竹菊影视 |