- How to Simplify your Android View Binding Delegation
- What is Android View Binding and How to simplify its delegation?
- What is View Binding?
- Why do we need it?
- How to use the View Binding?
- Now for the next question is, How do you make the binding delegation with just one-liner?
- Fragment View Binding initialisation using Delegates
- What are Delegates?
- Property Delegation
- A Custom Property Delegate for Fragment View Binding
- Делаем Android View Binding удобным c Kotlin
- Стандартный способ работы с View Binding
- Kotlin Delegated Property в бой
- Момент, когда что-то пошло не так.
- View binding delegate android
- About
- View binding delegate android
How to Simplify your Android View Binding Delegation
What is Android View Binding and How to simplify its delegation?
View Binding is part of Android Jetpack. View Binding was introduced at the Android Talk at Google IO/19. Let’s learn more about this.
What is View Binding?
View binding is a feature that allows you to more easily write code that interacts with views. Once view binding is enabled in a module, it generates a binding class for each XML layout file present in that module. An instance of a binding class contains direct references to all views that have an ID in the corresponding layout.
In most cases, view binding replaces findViewById .
Why do we need it?
When we use findViewById , we need to declare the view variable for x times we need to use it. It makes a lot of boilerplate code inside your view Activity/Fragment. That is why View Binding came to provide a good way to access all views with only initializing one variable.
This is how we use the findViewById :
And this is how we use the View Binding:
See the difference?
Yep, you only declare the binding variable from the generated view binding class. And you can access all of the view ids from the binding variable. Other advantages of using View Binding are:
Type Safety: View Binding provide a generated method of the same type as defined in the XML layout. So no more typecasting.
Null Safety: findViewById is not null safe either. If you are using Kotlin, it will save your pain of checking all of the null variables. Instead, for Java users, it will make them grab their keyboards and slam it to their monitors 😀
How to use the View Binding?
- Enable the viewBinding feature on your app/build.gradle :
2. After that, just create an XML layout. For example, create an activity_sample.xml.
3. Then, it will autogenerate the binding class and it will be accessed as ActivitySampleBinding class. Just for the record, If you don’t want the XML layout to be autogenerated, you can add tools:viewBindingIgnore=»true» to your root layout:
4. After that, inflate your ActivitySampleBinding class with your layout inflater.
5. In your Fragment, set the binding inflater inside your onCreateView and return the binding.root. You can see the full example here.
6. Accessing your view, you can just do this:
PS: If your view id uses the under_score, it will be generated as a camelCase variable.
7. And that’s it. You are done setting up your view using View Binding.
Now for the next question is, How do you make the binding delegation with just one-liner?
Kotlin is an extraordinary language, to make the binding delegation with just one-liner, we need to use the one of Kotlin property. It is Kotlin Property Delegates. See the explanation here.
I create this library to help me achieve one-liner delegation, it is built using Kotlin Property Delegates and combined with the Kotlin Extension Functions. So no more boilerplate for View Binding delegation in your view. See the library here.
Источник
Fragment View Binding initialisation using Delegates
View Binding in Android, allows us to seamlessly interact with the user interface by providing auto-generated classes for each XML layout (on a module by module basis).
Therefore, a routine task of setting text in a TextView can be transformed from this:
Of course, view binding requires some additional boilerplate code before we can use it. In the example above, we need to first initialise the binding .
Doing this for each fragment in our project is cumbersome. So, can we do better? Is there a cleaner, more efficient way that decreases our boilerplate code? Yes! By leveraging the power of Delegates.
The article assumes you have already set up view binding in your project. If not, refer this link to learn how to set it up.
What are Delegates?
Delegation is defined as the shifting of responsibility for some particular work from one person to another. Simply put, you can think of delegation as a process in which one object delegates (assigns/gives) a particular task to a helper object, called the delegate. It then becomes the responsibility of the delegate to execute the task and provide the result to our initial object. Kotlin inherently provides support for both class and property delegates. Since our binding object is a Fragment property, we’ll be working with property delegates.
Property Delegation
With property delegation, our delegate is responsible for handling the get and set for the specified property. We can thus abstract our common logic behind the delegate and re-use it for similar objects which in our case is the set of classes, auto-generated by view binding.
A thorough, more descriptive explanation of delegates can be found here.
A Custom Property Delegate for Fragment View Binding
Without further ado, let’s start writing our view binding delegate.
Step 1: Create the delegate class
Create a new class FragmentViewBindingDelegate.kt and implement the ReadOnlyProperty interface. In case your property is mutable, you can use the ReadWriteProperty interface but since our binding is immutable, we only extend the read only interface. In addition, we require the binding class in our delegate constructor.
Step 2: Implement the ReadOnlyProperty interface
As soon as we implement the ReadOnlyProperty interface, we are asked to implement the getValue member function.
The first param of getValue() is thisRef which represents the object that holds our property. It is of type Fragment in our case. The type for thisRef is governed by how we implement our interface. This is why we implemented ReadOnlyProperty instead of ReadOnlyProperty .
Step 3: Implement getValue
getValue() needs to return an instance of our binding object. So we create a variable called binding . In getValue() we initialise binding if it’s not initialised and return it. This ensures we only initialise binding once and subsequently re-use the same instance.
At this point, we have handled most of our boilerplate code and can initialise our binding as:
However, there are a few problems
1. The syntax to initialise binding can be improved
2. Our delegate is not lifecycle aware and thus, it will leak memory
Let’s resolve them. Read on.
Step 4: Clean our binding init syntax
Our delegate requires the class of our generic Class to return the correct view binding instance. Another way to get this information is by using the reified keyword in Kotlin. You can learn more about reified here.
Add this inline function outside your delegate class:
Et voilà! You can now initialise your binding with a clean, concise syntax.
Step 5: Make FragmentViewBindingDelegate lifecycle aware
To make our delegate lifecycle aware we need to pass an instance of our host fragment to it.
And, update our inline function.
Finally, subscribe to the fragment’s lifecycle and set the binding to null once the fragment is destroyed ensuring our delegate does not leak any memory.
Источник
Делаем Android View Binding удобным c Kotlin
Привет! Меня зовут Кирилл Розов. Я автор Telegram канала Android Broadcast. Очень люблю Kotlin и мне нравится с помощью его возможностей упрощать разработку. С такой задачей я недавно столкнулся, когда на новом Android проекте начали использовать View Binding.
Эта возможность появилась в Android Studio 3.6, но на самом деле она не совсем новая, а облегченный вариант Android Data Binding. Зачем столько усложнений? Проблема была в скорости — множество разработчиков использовали Android Data Binding только для генерации кода со ссылками на View и игнорировали другие возможности библиотеки. Чтобы ускорить генерацию кода, создали View Binding . Однако стандартный способ работы с ней — это дублирование кода от которого хочется избавиться.
Стандартный способ работы с View Binding
Разберем работу View Binding на примере Fragment. У нас есть layout ресурс с именем profile.xml (содержимое его неважно). Если мы хотим использовать ViewBinding, тогда в стандартном варианте это будет выглядеть так:
Проблема здесь несколько:
- Много лишнего кода
- Копи паста: каждый Fragment будет иметь аналогичный кусок кода
- Property viewBinding получается nullable и модифицируемым.
Давайте пробовать избавляться от этого с помощью Cилы Kotlin
Kotlin Delegated Property в бой
С помощью делегирования работы с property в Kotlin можно круто повторно использовать код и упростить некоторые задачи. Например, я применил это в случае с ViewBinding . Для этого я сделал свой делегат, который оборачивает создание ViewBinding и очистку его в нужный момент жизненного цикла:
и конечно же функцию-фабрику, чтобы не видеть как делегат создается:
После небольшого рефакторинга с новыми возможностями я получил следующее:
Вроде задача, которая ставилась, была достигнута. Что же могло пойти не так?
Момент, когда что-то пошло не так.
В какой-то момент возникла необходимость чистить View следующим образом:
Но в итоге я получил состояние, что моя ссылка на ViewBinding внутри делегируемого property уже была почищена. Попытка перенести очистку кода до вызова super.onDestroyView() не принесла успеха и я начал копаться в причинах. Виновником стала реализация вызова методов жизненного цикла у Fragment.viewLifecycleOwner .
Событие ON_DESTROY в Fragment.viewLifecycleOwner происходит до вызова Fragment.onDestroyView() , поэтому FragmentViewBindingProperty очищался раньше, чем я того ожидал. Решением стало отложить вызов операции очистки. Все вызовы жизненного цикла вызываются последовательно и на главном потоке, поэтому весь фикс свелся к откладыванию очистки с помощью Handler :
Полный код можно найти здесь и использовать его на своих проектах.
Источник
View binding delegate android
Make work with Android View Binding simpler. The library do:
- managing ViewBinding lifecycle and clear reference to it to prevent memory leaks
- you don’t need to keep nullable reference to Views or ViewBindings
- create ViewBinding lazy
The library has two variants: relection and without it. They were divided in separate artifacts: viewbindingpropertydelegate and viewbindingpropertydelegate-noreflection . Prefer to use variant without reflection for better performance
IMPORTANT: Enable ViewBinding before use the library
Every Gradle module of your project where you need use ViewBinding must be configured properly. How to do that you can find in the official guide
Add library to a project
Copyright 2020-2021 Kirill Rozov
Licensed under the Apache License, Version 2.0 (the «License»); you may not use this file except in compliance with the License. You may obtain a copy of the License at
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an «AS IS» BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
About
Make work with Android View Binding simpler
Источник
View binding delegate android
Read ViewBinding Delegate — one line to get details about implementation.
1. Add the JitPack repository to your build file
Add it in your root build.gradle at the end of repositories:
2. Add the dependency
1. Activity (with reflection). See example
2. Activity (without reflection): Pass ::bind method reference. See example
3. Fragment (with reflection). See example
4. Fragment (without reflection): Pass ::bind method reference. See example
5. Includes tag layout: Create 2 ViewBinding property. See example
6. The Dialog of DialogFragment See example
Extends DefaultViewBindingDialogFragment or implements ViewBindingDialogFragment .
Click to expand
Must setContentView before access ViewBinding property. This can be done easily with constructor :
Fragment ‘s View must be not null before access ViewBinding property. This can be done easily with constructor :
If there is any problem with Proguard , add below to your app/proguard-rules.pro :
4. Throws IllegalStateException : «Attempt to get view binding when fragment view is destroyed» when accessing delegate property in onDestroyView
Since version 1.0.0-alpha03 — Feb 16, 2021 , we cannot access ViewBinding delegate property in onDestroyView (this causes many problems). Recommended way is passing a lambda to onDestroyView: (T.() -> Unit)? = null parameter of extension functions, eg.
5. Min SDK version
Since version 1.2.0 , minSdkVersion has been changed to 14 .
Источник