Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why this strange behaviour of the `by lazy` delegate in fragments

A few days ago, I posted this question about using synthetic properties when you include the same layout in a screen multiple times.

The answer was awesome but after I tried it more for a few days, I noticed a strange behaviour:

When going forward from the fragment (the one containing the references to the view obtained by the lazy delegate) and then coming back ( I use transaction.commit() and manager.popBackStack(), to do this ), the labels will be empty. I already checked with the debugger if anything is null there, and nothing is.

The only solution that seems to work is replacing the by lazy with lateinit var and assigning them in onViewCreated.

Do you know why? Is the solution I used still "good" as a kotlin idiom?

I include the two pieces of code for the sake of completeness:

Partially working one:

private val foundTitle by lazy { detailContainer1.title }
private val foundDescription by lazy { detailContainer1.description }

private val wantedTitle by lazy { detailContainer2.title }
private val wantedDescription by lazy { detailContainer2.description }

Always working one:

 private lateinit var foundTitle: TextView
 private lateinit var foundDescription: TextView

 private lateinit var wantedTitle: TextView
 private lateinit var wantedDescription: TextView

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

   foundTitle = detailContainer1.title
   foundDescription = detailContainer1.description

   wantedTitle = detailContainer2.title
   wantedDescription = detailContainer2.description

 }

Thanks in advance

like image 872
Jibbo Avatar asked Aug 17 '18 12:08

Jibbo


People also ask

What does by lazy do in Kotlin?

Lazy is mainly used when you want to access some read-only property because the same object is accessed throughout.

What is the difference between lazy and Lateinit?

lateinit can only be used with a var property whereas lazy will always be used with val property. A lateinit property can be reinitialised again and again as per the use whereas the lazy property can only be initialised once.

How do you use lazy in Kotlin example?

Example. In this example, we will declare a lazy variable "myName" and we could see that the call to this parts of the code will happen only once and when the value is initialized, it will remember the value throughout the application. Once the value is assigned using lazy initialization, it cannot be reassigned .

Which property allows you to avoid initialising a property when an object is declared?

Lazy Properties. It's a common pattern in software engineering to put off creating and initializing an object until it is actually needed. This pattern is known as lazy initialization, and is especially common on Android, since allocating a lot of objects during app startup can lead to a longer startup time.

What is lazykt Myname $delegate?

Note that the type of myName$delegate is Lazy, not String. In the constructor, LazyKt.lazy () is assigned to myName$delegate. LazyKt.lazy () is responsible for executing the given initialization block.

What is lazy in Kotlin?

Simply, lazy creates an instance that performs initialization at the first access to the property value, stores the result, and returns the stored value. Let's write a simple Kotlin code to check the implementation of lazy. If you do decompiling it to Java code, you can see the following code:

What is delegation in object oriented programming?

What’s Delegation? In general, Delegation refers to passing responsibility of one to another in order to achieve code- reuse in Object Oriented Programming. It prevents implementing the same code again and again.

How does lazy getter work in Python?

The first call of getter executes a lambda passed to lazy () and stores its result. Subsequently, the getter execution returns the stored value. Simply, lazy creates an instance that performs initialization at the first access to the property value, stores the result, and returns the stored value.


Video Answer


1 Answers

Fragment's have their view destroyed when they get removed - but lazy fields do not clear their reference so they are essentially leaking previous view.

If possible You should always have unique view IDs within your project, even if they are not within same layout - having duplicates can cause multiple problems (like yours).

If you were able to use kotlin extensions directly, it would generate code for finding, caching and clearing the view cache when fragments view is destroyed automatically.

Try to "get" views from fragments cache instead of assigning them to fields:

private val foundTitle 
    get() = detailContainer1.title
private val foundDescription
    get() = detailContainer1.description

private val wantedTitle
    get() = detailContainer2.title
private val wantedDescription
    get() = detailContainer2.description
like image 137
Pawel Avatar answered Oct 21 '22 08:10

Pawel