it-swarm.dev

Nierozwiązane odniesienie do widoku syntetycznego, gdy układ znajduje się w module biblioteki

używając Kotlin 1.20.20 (nie ma to znaczenia, starsze wersje zachowują się tak samo)

Gdy układ jest w osobnym module biblioteki, Android Studio nie ma problemu ze znalezieniem i odniesieniem widoku

import kotlinx.Android.synthetic.main.view_user_input.*

Ale kiedy próbuję skompilować aplikację, kończy się niepowodzeniem z Unresolved reference: view_user_input na :app:compileDebugKotlin.

Wszystko działa dobrze, gdy widok jest odwoływany w module biblioteki.

Czy coś mi umyka?

Dodawanie struktury projektu. Wszystkie moduły używają rozszerzeń kotlin i kotlin.

build.gradle
app/
  build.gradle //main application
library-module-a/
  build.gradle //library application
library-module-b/
  build.gradle //library application

Oto przykładowa aplikacja https://github.com/mjurkus/KotlinxTest

Zarejestrowany problem w KT tracker

10
Martynas Jurkus

Jednym ze sposobów rozwiązania tego jest utworzenie właściwości „alias”, którą można wykorzystać z innych modułów:

// SyntheticExports.kt
package com.example.synthetic.exported

import kotlinx.Android.synthetic.main.layout_in_library.*

inline val Activity.exported_text_view get() = text_view

Następnie na drugim module:

// MainActivity.kt
import com.example.synthetic.exported.exported_text_view

exported_text_view.text = "example"

To działa dla nas. Musisz utworzyć różne rozszerzenia dla view, fragment itp. Trochę żmudne jest robić to ręcznie, ale jest to najprostsze obejście, jakie znaleźliśmy.

Extra: Jest to również przyzwoita metoda eksportowania rozszerzeń syntetycznych jako części biblioteki publicznej, a nie tylko w module wewnętrznym.

3
pablisco

Warunki wstępne

Nie importuj następującej biblioteki import kotlinx.Android.synthetic.main.my_view.view.*

app/MainActivity.kt

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val view: View = MyView(this)
        view.findViewById<TextView>(R.id.textViewPocLib).text = "I can edit the library components"
        setContentView(view)
}

my_library/MyView.kt

class MyView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
    LinearLayout(context, attrs, defStyleAttr) {

    init {
        LayoutInflater.from(context)
            .inflate(R.layout.my_view, this, true)
    }
}

GL

Źródła:

1
CORONEL Braian

możesz spróbować przełączyć się na 1.2.30-eap-16 i dodać

androidExtensions { experimental = true }

na twój build.gradle.

1
Ivan Morgillo

Dostałem także ten problem i moim rozwiązaniem jest:

  • Nie używaj import kotlinx.Android.synthetic.main .... *

  • Użyj findViewById ()

Np .: textview_id.text = "abc". Zmieniłem go na findViewById (R.id.textview_id) .text = "abc"

1
Anh Duy

Jak wspomniano w komentarzu przez @cesards powyżej, jest to trwający problem z rozszerzeniem Kotlin Android. I to nie jest rozwiązane od dzisiaj.


Dobrze: użyj widoków niestandardowych

Moją podstawową sugestią jest hermetyzacja widoku i odpowiedniego zachowania jako widoku niestandardowego i zamiast dołączania go do tagu <include>, używaj go bezpośrednio w swoim układzie jako <com.example.app.YourCustomView>.

To działa bez względu na to, czy klasa widoku znajduje się w innym module, czy nie.


Bad and Ugly: Id Collision Workaround

Jednak znalazłem hacky obejście, jeśli chcesz tylko uzyskać jedno odwołanie z dołączonego widoku.

Wykonaj poniższe kroki, aby użyć syntetycznych importów kotlin dla układów zawartych w innych modułach:

  1. Podaj identyfikator widoku, do którego chcesz uzyskać odniesienie w dołączonym pliku xml.
  2. Podaj ten sam identyfikator tagowi include w dołączonym pliku xml.
  3. Teraz syntetyczny import widoku (id) z dołączonego układu (nie z dołączonego)

Nie jestem pewien, jak i dlaczego to działa, ale jest to bardzo delikatny i brudny sposób na ponowne wykorzystanie układów.

Przykład:

Twój włącznie z układem (fragment_example.xml)

<include
    Android:id="@+id/exampleView"
    layout="@layout/example_layout" />

Twój dołączony układ (example_layout.xml)

<merge xmlns:Android="http://schemas.Android.com/apk/res/Android">

    <TextView
        Android:id="@+id/exampleView"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content" />

</merge>

Twoja klasa fragmentu (ExampleFragment.kt)

import kotlinx.Android.synthetic.main.fragment_example.exampleView

// Do not import the exampleView through example_layout.exampleView

class ExampleFragment : Fragment() {
    // Do something with imported exampleView
}
0
SafaOrhan