Kotlin Android 提供布局空指针的扩展
Kotlin Android Extensions giving Layout Null Pointer
有一个相当简单的场景给我带来了很多麻烦。我正在制作一个带有嵌入式片段的非常简单的 Activity。这个片段只是一个显示一些图像的 Gridview。使用 Kotlin 扩展引用 Gridview 以直接引用 XML id 时会出现问题。 这里有什么问题?
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"/>
Parent Activity布局
<?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)
}
}
要在 Fragment 中使用扩展,您需要使用 layoutView
。
这应该有效:layoutView.gridview_all_parts.adapter = MasterListAdapter(activity, AndroidImageAssets.getAll())
在这种情况下,您可以将布局视图设为全局视图。
更新说明
它与视图膨胀有关。就像在 butterknife 中一样,我们需要在 fragment/recyclerView 的情况下绑定膨胀视图,同样在 kotlin 的情况下,我们需要膨胀视图来访问 xml.
中的视图
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
kotlinx.android.synthetic.main.activity_main.*.
If we want to call the synthetic properties on View, we should also
import
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.
对于在另一个案例中发现此问题的所有人。
来自Android Extensions 的NPE 也发生在我们为RecyclerView 编写适配器时(特别是:编写CustomViewHolder)。
有关详细信息以及如何解决此问题,请参阅 LayoutContainer。
- 将此添加到您的模块级别 gradle
apply plugin: 'kotlin-android-extensions'
android {
androidExtensions {
experimental = true
}
// your config
defaultConfig {}
}
- 你的适配器
class MainViewHolder(override val containerView: View) :
RecyclerView.ViewHolder(containerView),
LayoutContainer { // Extends this
fun bind(item: News) = containerView.apply {
tv_item_title.text = item.title
}
}
有一个相当简单的场景给我带来了很多麻烦。我正在制作一个带有嵌入式片段的非常简单的 Activity。这个片段只是一个显示一些图像的 Gridview。使用 Kotlin 扩展引用 Gridview 以直接引用 XML id 时会出现问题。 这里有什么问题? 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"/>
Parent Activity布局
<?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)
}
}
要在 Fragment 中使用扩展,您需要使用 layoutView
。
这应该有效:layoutView.gridview_all_parts.adapter = MasterListAdapter(activity, AndroidImageAssets.getAll())
在这种情况下,您可以将布局视图设为全局视图。
更新说明 它与视图膨胀有关。就像在 butterknife 中一样,我们需要在 fragment/recyclerView 的情况下绑定膨胀视图,同样在 kotlin 的情况下,我们需要膨胀视图来访问 xml.
中的视图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 importkotlinx.android.synthetic.main.activity_main.*.
If we want to call the synthetic properties on View, we should also import
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.
对于在另一个案例中发现此问题的所有人。
来自Android Extensions 的NPE 也发生在我们为RecyclerView 编写适配器时(特别是:编写CustomViewHolder)。
有关详细信息以及如何解决此问题,请参阅 LayoutContainer。
- 将此添加到您的模块级别 gradle
apply plugin: 'kotlin-android-extensions'
android {
androidExtensions {
experimental = true
}
// your config
defaultConfig {}
}
- 你的适配器
class MainViewHolder(override val containerView: View) :
RecyclerView.ViewHolder(containerView),
LayoutContainer { // Extends this
fun bind(item: News) = containerView.apply {
tv_item_title.text = item.title
}
}