7

I'm new to Kotlin. Among other very interesting things, I've found the Android extensions which, according to the documentation, should let me use activities' views without the need of findViewById.

Actually it works very well by adding just this line in my imports:

import kotlinx.android.synthetic.main.<layout>.*

The problem is when two different layouts contain a widget with the same id (i.e. the same name for the synthetic property),
e.g. two different TextViews with the id txtTitle. Say the first one is on an activity and the second one belongs to the layout used inside of an adapter.

When I try to call a method on the first TextView (the activity's one) I can't see the expected result, as if the call would be done on another view. As confirmation of this, when I call txtTitle.parent, I see the parent and the siblings of the other txtTitle rather than the ones expected.

Am I doing something wrong? The only ways I've found to bypass this issue is to use different names in all my layouts or continue to use findViewById, but it would be a pity to waste this language feature...

Massimo
  • 3,436
  • 4
  • 40
  • 68
  • I'd like to recommend you to use more complex names for your IDs :) It prevents from "playing" with imports in my case as well. – UneXp Jan 24 '17 at 09:00
  • Not sure if this answers your question, but the synthetic calls are translated to calls to `findviewById` and because every id **name** is mapped to a unique value, it doesn't matter *which* import you use as long as you use one with the correct name. – Kirill Rakhman Jan 24 '17 at 10:13
  • I imagined, but actually it is working bad. I have an activity with a txtTitle, inside of this activity there is a fragment with a RecyclerView: inside of the RecyclerView there are views with a txtTitle. I'm just seeing what I wrote: when I use the txtTitle inside of the activity it does not produce the expected result (it does not set the TextView's text); instead, if I use findViewById() from the activity it works correctly... – Massimo Jan 24 '17 at 12:09
  • Honestly I don't think each call to a synthetic property is translated to a findViewById, it would be terrible for performances. I hope they will solve this bug in the next version of the Android extensions – Massimo Jan 30 '17 at 11:24
  • According to the book _Kotlin for Android Developers_: How does it [synthetic views] work under the hood? The plugin substitutes any properties call into a function that requests the view, and a caching function that **prevents from having to find the view every time a property is called.** So it **is** translated into findViewById but there is a caching mechanism so that findViewById is called only once for each View. – bartonstanley Jun 21 '17 at 16:00

3 Answers3

6

The kotlin documentation on imports says

If there is a name clash, we can disambiguate by using as keyword to locally rename the clashing entity

So you could try to import the layouts with different aliases:

import kotlinx.android.synthetic.main.<layoutActivity>.* as lActivity
import kotlinx.android.synthetic.main.<layoutView>.* as lView

And use the textviews with the corresponding qualifier: lActivity.txtTitle and lView.txtTitle

Lukas Lechner
  • 7,881
  • 7
  • 40
  • 53
  • 6
    I can't use the "as" keyword on a multiple import statement, the IDE (Android Studio) warns me with the message "Cannot rename all imported items to one identifier". Furthermore, in my activity I have not the import of the layout, because it is used by a fragment (attached to the activity), not by the activity. – Massimo Jan 24 '17 at 08:57
3

You can try below thing for TextView having same id from different layout.

import kotlinx.android.synthetic.main.activity_main.text_hello as lActivity

import kotlinx.android.synthetic.main.extra_layout.text_hello as lView

use lActivity.text = "Some text" for TextView from activity_main and lView.text = "Some text" for TextView from extra_layout.

peter.hrasko.sk
  • 4,043
  • 2
  • 19
  • 34
paril
  • 1,850
  • 2
  • 14
  • 26
0

Another possible solution to your problem is to just import one and omit the other, assuming all the IDs you need are present in that one.

At the end of the day, similar IDs point to the same thing, and it doesn't really matter whether it was imported from one layout or the other.

Hope that helps

Kingsley Adio
  • 728
  • 5
  • 16