Не вдається “findViewById” у Котліні. Отримання помилки "Помилка виведення типу"


80

Я отримую таку помилку, коли намагаюся знайти RecycleViewідентифікатор.

Помилка: - Помилка виведення типу: Недостатньо інформації для виведення параметра T

Помилка

Код:

class FirstRecycleViewExample : AppCompatActivity() {
    val data = arrayListOf<String>()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.first_recycleview)

        val recycler_view =  findViewById(R.id.recycler_view) as RecyclerView ///IN THIS LINE I AM GETTING THE ERROR

        data.add("First Data")
        data.add("Second Data")
        data.add("Third Data")
        data.add("Forth Data")
        data.add("Fifth Data")

        //creating our adapter
        val adapter = CustomRecycleAdapter(data)

        //now adding the adapter to recyclerview
        recycler_view.adapter = adapter
    }
}

Відповіді:


101

Спробуйте щось на зразок:

val recyclerView = findViewById<RecyclerView>(R.id.recycler_view)

Ви також можете використовувати Kotlin Android Extensionsдля цього. Перевірте документ тут .
За допомогою нього ви можете телефонувати recycler_viewбезпосередньо у своєму коді.

Розширення Kotlin для Android:

  • У додаток gradle.buildдодайтеapply plugin: 'kotlin-android-extensions'
  • У своєму класі додайте імпорт, import kotlinx.android.synthetic.main.<layout>.*де <layout>є ім'я файлу вашого макета.
  • Ось і все, ви можете зателефонувати recycler_viewбезпосередньо у своєму коді.

Як це працює? Перший раз, коли ви телефонуєте recycler_view, дзвінок findViewByIdвиконується та кешується .


В останній версії я отримую попередження про видалення типу з <>. Оскільки студія Android змушує мене використовувати лише алмазний оператор, <>коли я його використовую, це видає помилку.
Асіф Муштак

46

Ви перебуваєте на рівні API 26, де тип повернення findViewByIdтепер є загальним, Tа не Viewі тому можна зробити висновок. Ви можете побачити відповідний журнал змін тут .

Отже, ви повинні мати можливість зробити це:

val recycler_view = findViewById<RecyclerView>(R.id.recycler_view)

Або це:

val recycler_view: RecyclerView = findViewById(R.id.recycler_view)

7

У Kotlinнас ми можемо отримати ідентифікатор подання без використання findViewByIdсинтаксису.

Наприклад, ми використовуємо наступний макет, з якого ми отримаємо ідентифікатор подання та виконаємо операцію

Макет

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/welcomeMessage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="Hello World!"/>

</FrameLayout>

Ми можемо знайти ідентифікатор подання, використовуючи наступний код

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    welcomeMessage.text = "Hello Kotlin!" ////WE ARE GETTING THE IDS WITHOUT USING THE FINDVIEWBYID syntax
}

ЯК?

Щоб мати змогу ним користуватися, вам потрібен спеціальний імпорт (той, який я пишу нижче), але IDE може його автоматично імпортувати. Не може бути простіше!

import kotlinx.android.synthetic.main.YOUR_LAYOUT_NAME.*/// HERE "YOUR_LAYOUT_NAME" IS YOUR LAYOUT NAME WHICH U HAVE INFLATED IN onCreate()/onCreateView() 

Нам потрібно імпортувати цю властивість, щоб отримати ідентифікатор подання без використання findviewbyidсинтаксису.

Для отримання додаткової інформації по цій темі, ніж будь ласка, перейдіть за цим посиланням: - Клацніть тут


1
Блискуче рішення! Мені дуже допомогло!
gundrabur

7

Зазвичай Kotlin може зробити висновок про ваш тип, використовуючи інформацію, подану в дужках.

У цьому випадку це неможливо, тому вам доведеться вказувати це явно так

findViewById<RecyclerView>(R.id.recycler_view)

Насправді не впевнений у типі, але саме так вам слід його вказати

Я хотів би додати, що, використовуючи Anko , ви можете ще більше спростити свій код так:

val recycler_view : RecyclerView =  find(R.id.recycler_view)


2

Ви можете ігнорувати надання ідентифікаторів змінним у kotlin. Вам просто потрібно використовувати плагін

Вставте це у свою градацію

 apply plugin: 'kotlin-android-extensions'

і тоді вам не потрібно призначати ідентифікатори var, ви можете просто зробити це як

 recycler_view.setAdapter(youradapter);

Будь ласка, вкажіть причину для голосування проти.
Anmol317,

1

Спробуйте це:

Тут bindзагальна функція використовується для прив'язки подання. його загальну функцію, яку він може використовувати для будь-якого подання.

class MyActivity : AppCompatActivity() {
    private lateinit var recycler_view : RecyclerView
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        recycler_view = bind(R.id.recycler_view)
    }
}

fun <T : View> Activity.bind(@IdRes res : Int) : T {
    @Suppress("UNCHECKED_CAST")    
    return findViewById(res) as T
}

1
Будь ласка, додайте пояснення до свого коду. Не рекомендується відповідати лише з кодом.
Віллі Менцель

1
додано. @WilliMentzel
Mehul Kabaria

0

Вам навіть не потрібно створювати об’єкт, щоб робити речі з видом. Ви можете просто використовувати ідентифікатор. Наприклад, Котлін

recycle_view.adapter = adapter

те саме, що і Java

RecycleView recycle_view = (RecycleView) findViewById(recycle_view);
recycle_view.setAdapter(adapter);

0

Не вдалося отримати доступ до компонентів інтерфейсу, таких як OP, схоже на те, що нижче потрібно було всередині програми gradle:

plugins {
    ...
    id 'kotlin-android-extensions'
}

Навіть незважаючи на те, що після додавання цього рядка, андроїд-студія все ще не змогла автоматично вирішити імпорт синтетики kotlin, тому вам може знадобитися анулювати кеш і перезапустити.

Якщо все ще не працює, імпортуйте вручну залежно від подань

  • перегляд активності / фрагмента: імпорт kotlinx.android.synthetic.main. <ваш_вигляд_діяльності>. *
  • звичайні перегляди: імпортувати kotlinx.android.synthetic.main. <your_layout_view> .view. *

Оновлення - 2

Якщо ви отримуєте це інформаційне попередження -

Попередження: Плагін Gradle 'kotlin-android-extensions' застарілий.

плагін 'kotlin-android-extensions' буде застарілим. Тож додайте нижче у свій додаток gradle

android {
    ...
    buildFeatures {
        viewBinding true
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.