简体   繁体   English

Kotlin Android Extensions提供布局空指针

[英]Kotlin Android Extensions giving Layout Null Pointer

There is a fairly simple scenario that is giving me quite a bit of trouble. 有一个相当简单的场景给我带来了很多麻烦。 I'm making a very simple Activity with an embedded fragment. 我正在使用嵌入式片段制作一个非常简单的Activity。 This fragment is simply a Gridview that displays some images. 这个片段只是一个显示一些图像的Gridview。 The issue comes when referring to the Gridview using Kotlin extensions to refer directly to an XML id. 当引用使用Kotlin扩展的Gridview直接引用XML id时会出现问题。 What is the issue here? 这是什么问题? Does kotlinx not work on static fragments? kotlinx不能用于静态片段吗?

Error: 错误:

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 with offensive line of code 带有令人反感的代码行的片段

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

Parent Activity Layout 父活动布局

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

Parent Activity 家长活动

class MainActivity: AppCompatActivity(){

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

To use the extensions in Fragment, you need to use with your layoutView . 要在Fragment中使用扩展,您需要使用layoutView This should work: layoutView.gridview_all_parts.adapter = MasterListAdapter(activity, AndroidImageAssets.getAll()) 这应该工作: layoutView.gridview_all_parts.adapter = MasterListAdapter(activity, AndroidImageAssets.getAll())

You can make your layoutView global in this case. 在这种情况下,您可以使layoutView全局化。

UPDATED EXPLANATION Its something to do with view inflating. 更新的解释它与视图膨胀有关。 Like in butterknife, we need to bind the inflated view in case of fragment/recyclerView, similarly in case of kotlin, we need that inflate view for accessing the views in the xml. 就像在butterknife中一样,我们需要在fragment / recyclerView的情况下绑定膨胀的视图,类似于kotlin,我们需要使用inflate视图来访问xml中的视图。

Quoting from official documentation , 引自官方文件

Importing synthetic properties It is convenient to import all widget properties for a specific layout in one go: 导入合成属性可以一次导入特定布局的所有窗口小部件属性:

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

Thus if the layout filename is activity_main.xml , we'd import 因此,如果布局文件名是activity_main.xml ,我们将导入

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

If we want to call the synthetic properties on View, we should also import 如果我们想在View上调用合成属性,我们也应该导入

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

Once we do that, we can then invoke the corresponding extensions, which are properties named after the views in the XML file. 一旦我们这样做,我们就可以调用相应的扩展,这些扩展是以XML文件中的视图命名的属性。

For everyone who found this problem in the other case. 对于在其他情况下发现此问题的每个人。

The NPE from Android Extensions also occurs when we write the adapter for RecyclerView (especially: writing CustomViewHolder). 当我们为RecyclerView编写适配器时,Android Extensions中的NPE也会出现(特别是:编写CustomViewHolder)。

See LayoutContainer for more info and how to fix this issue. 有关详细信息以及如何解决此问题,请参阅LayoutContainer

  1. Add this into your module level gradle 将其添加到模块级gradle中
apply plugin: 'kotlin-android-extensions'

android {
    androidExtensions {
        experimental = true
    }
    // your config
    defaultConfig {}
}
  1. Your adapter 你的适配器
class MainViewHolder(override val containerView: View) :
    RecyclerView.ViewHolder(containerView), 
    LayoutContainer { // Extends this
        fun bind(item: News) = containerView.apply {
            tv_item_title.text = item.title
        }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM