Kotlin Android Extensions, дающий макет Null Pointer

Существует довольно простой сценарий, который дает мне немного неприятностей. Я делаю очень простое действие со встроенным фрагментом. Этот фрагмент представляет собой просто Gridview, который отображает некоторые изображения. Проблема возникает при обращении к Gridview с использованием расширений Kotlin для прямого обращения к идентификатору XML. В чем проблема? Не работает ли kotlinx на статических фрагментах?

Ошибка:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.android.android_me/com.example.android.android_me.ui.MainActivity}: java.lang.IllegalStateException: gridview_all_parts must not be null
 Caused by: java.lang.IllegalStateException: gridview_all_parts must not be null                                                                                  at com.example.android.android_me.ui.MasterListFragment.onActivityCreated(MasterListFragment.kt:22)

Фрагмент с наступательной строкой кода

import kotlinx.android.synthetic.main.fragment_master_list.*

    class MasterListFragment: Fragment() {

        override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
            val layoutView = inflater?.inflate(R.layout.fragment_master_list, container, false)
            return layoutView
        }

        override fun onActivityCreated(savedInstanceState: Bundle?) {
            //If this is removed, code runs
            gridview_all_parts.adapter = MasterListAdapter(activity, AndroidImageAssets.getAll())
            super.onActivityCreated(savedInstanceState)
        }
    }

Макет фрагмента:

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

Макет родительской активности

<?xml version="1.0" encoding="utf-8"?>
<!--have tried both class:= and android:name:=-->
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    class="com.example.android.android_me.ui.MasterListFragment"
    android:id="@+id/fragment_masterlist"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    />

Родительская активность

class MainActivity: AppCompatActivity(){

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

Ответы

Ответ 1

Чтобы использовать расширения в Fragment, вам нужно использовать с вашим layoutView. Это должно работать: layoutView.gridview_all_parts.adapter = MasterListAdapter(activity, AndroidImageAssets.getAll())

В этом случае вы можете сделать layoutView глобальным.

ОБНОВЛЕННОЕ ОБЪЯСНЕНИЕ Его что-то делать с видом раздувания. Как и в butterknife, нам нужно связать раздутое представление в случае фрагмента /recyclerView, аналогично в случае kotlin, нам нужно, чтобы надуть представление для доступа к представлениям в xml.

Цитируя официальную документацию,

Импорт синтетических свойств Удобно импортировать все свойства виджета для определенного макета за один раз:

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

Таким образом, если имя файла макета - activity_main.xml, мы импортируем

kotlinx.android.synthetic.main.activity_main. *.

Если мы хотим назвать синтетические свойства в представлении, мы также должны импортировать

kotlinx.android.synthetic.main.activity_main.view.*.

Как только мы это сделаем, мы сможем затем вызвать соответствующие расширения, которые являются свойствами, названными после представлений в файле XML.

Ответ 2

Для всех, кто нашел эту проблему в другом случае.

NPE из Android Extensions также происходит, когда мы пишем адаптер для RecyclerView (особенно: пишем CustomViewHolder).

Посмотрите LayoutContainer для получения дополнительной информации и как исправить эту проблему.

  1. Добавьте это в свой уровень Gradle
apply plugin: 'kotlin-android-extensions'

android {
    androidExtensions {
        experimental = true
    }
    // your config
    defaultConfig {}
}
  1. Ваш адаптер
class MainViewHolder(override val containerView: View) :
    RecyclerView.ViewHolder(containerView), 
    LayoutContainer { // Extends this
        fun bind(item: News) = containerView.apply {
            tv_item_title.text = item.title
        }
}