web-dev-qa-db-fra.com

Extensions Kotlin Android donnant le pointeur nul à la mise en page

Il existe un scénario assez simple qui me donne pas mal de problèmes. Je fais une activité très simple avec un fragment incorporé. Ce fragment est simplement une Gridview qui affiche des images. Le problème vient de la référence à Gridview utilisant des extensions Kotlin pour faire directement référence à un identifiant XML. Quel est le problème ici? Kotlinx ne fonctionne-t-il pas sur les fragments statiques?

Erreur:

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)

Fragment avec une ligne de code offensive

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)
        }
    }

Fragment Layout:

<?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"/>

Présentation de l'activité des parents

<?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"
    />

Activité des parents

class MainActivity: AppCompatActivity(){

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

Pour utiliser les extensions dans Fragment, vous devez utiliser votre layoutView. Cela devrait fonctionner: layoutView.gridview_all_parts.adapter = MasterListAdapter(activity, AndroidImageAssets.getAll())

Vous pouvez rendre votre layoutView global dans ce cas.

EXPLICATION MISE À JOUR Elle a quelque chose à voir avec le gonflage de la vue. Comme dans butterknife, nous devons lier la vue gonflée dans le cas de fragment/recyclerView, de la même manière que dans le cas de kotlin, nous avons besoin de cette vue gonflée pour accéder aux vues dans le fichier XML.

Citant à partir de documentation officielle ,

Importation de propriétés synthétiques Il est pratique d'importer toutes les propriétés de widget pour une mise en page spécifique en une fois:

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

Ainsi, si le nom du fichier de mise en page est activity_main.xml, nous importons 

kotlinx.Android.synthetic.main.activity_main. *.

Si nous voulons appeler les propriétés synthétiques sur View, nous devrions également importation

kotlinx.Android.synthetic.main.activity_main.view.*.

Une fois que nous avons fait cela, nous pouvons ensuite appeler les extensions correspondantes, qui sont des propriétés nommées d'après les vues du fichier XML.

19
karandeep singh

Pour tous ceux qui ont trouvé ce problème dans l’autre cas.

Les NPE à partir d’extensions Android se produisent également lors de l’écriture de l’adaptateur pour RecyclerView (en particulier: l’écriture de CustomViewHolder). 

Voir LayoutContainer pour plus d'informations et pour résoudre ce problème.

  1. Ajoutez ceci dans votre niveau de module
apply plugin: 'kotlin-Android-extensions'

Android {
    androidExtensions {
        experimental = true
    }
    // your config
    defaultConfig {}
}
  1. Votre adaptateur
class MainViewHolder(override val containerView: View) :
    RecyclerView.ViewHolder(containerView), 
    LayoutContainer { // Extends this
        fun bind(item: News) = containerView.apply {
            tv_item_title.text = item.title
        }
}
0
mochadwi