尽管已经声明了文本,但 TextView 出现空错误
Posted
技术标签:
【中文标题】尽管已经声明了文本,但 TextView 出现空错误【英文标题】:TextView null error despite text already declared 【发布时间】:2019-05-17 03:23:36 【问题描述】:我试图在我的RecyclerView
中显示Strings
的数组,但即使如此,我也会遇到与空值相关的错误。我已经扫描了代码,但我看不出我做错了什么。在部署过程中,logcat 返回此错误:
txtTitle 不能为空
class MyFragment : androidx.fragment.app.Fragment()
private val ITEMTYPE = 100
private val HEADERTYPE = 101
private val INFOTYPE = 102
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View?
return inflater.inflate(R.layout.fragment_rv, container, false)
private lateinit var mRecyclerView: RecyclerView
private lateinit var dataTitle: ArrayList<CharSequence>
private lateinit var dataRating: ArrayList<String>
private lateinit var dataDescription: ArrayList<String>
private lateinit var mAdapter: RecyclerView.Adapter<com.companyname.appname.MyFragment.ViewHolder>
override fun onActivityCreated(savedInstanceState: Bundle?)
val v = view
mRecyclerView = v!!.findViewById(R.id.my_recyclerview)
// set the linear layout manager
mRecyclerView.layoutManager = LinearLayoutManager(activity, RecyclerView.VERTICAL, false)
// SpannableStrings
// dynamically change SpannableString colour using defined attribute
val attrS = intArrayOf(R.attr.spannablestringtextColor)
val ta = activity!!.theme.obtainStyledAttributes(attrS)
val colorSS = ta.getColor(0, Color.BLACK) //Color.BLACK - default value (colour will change automatically depending on chosen theme)
ta.recycle()
// SpannableString (start)
val ssb1 = SpannableStringBuilder()
val str1a = SpannableString(getString(R.string.placeholder1_placeholder2_placeholder3,
" ", getString(R.string.product_a), " "))
str1a.setSpan(BackgroundColorSpan(Color.BLACK), 0, str1a.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
str1a.setSpan(ForegroundColorSpan(ContextCompat.getColor(context!!, R.color.green)), 0, str1a.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
ssb1.append(str1a)
val str1b = SpannableString(" " + getString(R.string.producta_feature))
str1b.setSpan(ForegroundColorSpan(colorSS), 0, str1b.length, 0)
ssb1.append(str1b)
// SpannableString (end)
// init data
dataTitle = ArrayList()
dataTitle.add(ssbA)
dataTitle.add(getString(R.string.title_b))
dataRating = ArrayList()
dataRating.add(getString(R.string.rating_a))
dataRating.add(getString(R.string.rating_b))
dataDescription = ArrayList()
dataDescription.add(getString(R.string.description_a))
dataDescription.add(getString(R.string.description_b))
// create the adapter
mAdapter = createAdapter()
// set the adapter
mRecyclerView.adapter = mAdapter
super.onActivityCreated(savedInstanceState)
private fun createAdapter(): RecyclerView.Adapter<com.companyname.appname.MyFragment.ViewHolder>
return object : RecyclerView.Adapter<com.companyname.appname.MyFragment.ViewHolder>()
override fun onCreateViewHolder(parent: ViewGroup, type: Int): com.companyname.appname.MyFragment.ViewHolder
return when (type)
HEADERTYPE -> com.companyname.appname.MyFragment.ViewHolder(inflateHelper(R.layout.rv_header, parent))
INFOTYPE -> com.companyname.appname.MyFragment.ViewHolder(inflateHelper(R.layout.rv_info, parent))
ITEMTYPE -> com.companyname.appname.MyFragment.ViewHolder(inflateHelper(R.layout.rv_item, parent))
else -> com.companyname.appname.MyFragment.ViewHolder(inflateHelper(R.layout.rv_item, parent))
override fun onBindViewHolder(viewHolder: com.companyname.appname.MyFragment.ViewHolder, position: Int)
val rlProductInformation = viewHolder.itemView.findViewById<RelativeLayout>(R.id.rl_product_information)
when (getItemViewType(position))
HEADERTYPE ->
val buyButton = viewHolder.itemView.findViewById<Button>(R.id.buy_product)
buyButton.setText(R.string.buy)
INTROTYPE ->
val tvIntroA = viewHolder.itemView.findViewById<TextView>(R.id.tv_product_intro_A)
val tvIntroB = viewHolder.itemView.findViewById<TextView>(R.id.tv_product_intro_B)
ITEMTYPE ->
val itemA = dataTitle[position]
val itemB = dataRating[position]
val itemC = dataDescription[position]
viewHolder.tvTitle.text = itemA
viewHolder.tvSubtitle.text = itemB
viewHolder.tvDescription.text = itemC
override fun getItemCount(): Int
return dataTitle.size + 2
override fun getItemViewType(position: Int): Int
return when (position)
0 -> HEADERTYPE
else -> ITEMTYPE
private fun inflateHelper(resId: Int, parent: ViewGroup): View
return LayoutInflater.from(activity).inflate(resId, parent, false)
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
internal class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
var tvTitle: TextView = itemView.findViewById(R.id.tv_product_title) as TextView
var tvSubtitle: TextView = itemView.findViewById(R.id.tv_product_rating) as TextView
var tvDescription: TextView = itemView.findViewById(R.id.tv_product_description) as TextView
init
tvTitle; tvSubtitle; tvDescription
RecyclerView XML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/linearLayout_recyclerView"
android:orientation="vertical"
android:layout_
android:layout_>
<androidx.recyclerview.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/my_recyclerview"
android:clipToPadding="false"
android:layout_
android:layout_
android:scrollbars="vertical"
android:scrollbarSize="3dp">
</androidx.recyclerview.widget.RecyclerView>
</LinearLayout>
RecyclerView 项目 XML
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/cv_product"
android:layout_
android:layout_
app:contentPadding="16dp"
android:layout_marginBottom="30dp">
<LinearLayout
android:id="@+id/ll_cv_product"
android:layout_
android:layout_
android:orientation="vertical">
<LinearLayout
android:id="@+id/cv_product_title"
android:layout_
android:layout_
android:orientation="horizontal"
android:layout_marginBottom="2dp">
<TextView
android:id="@+id/tv_product_title"
android:layout_
android:layout_
style="@android:style/TextAppearance.Large" />
</LinearLayout>
<RelativeLayout
android:id="@+id/rl_product_information"
android:layout_
android:layout_>
<TextView
android:id="@+id/tv_product_new"
android:layout_
android:layout_
android:text="@string/board"
android:textColor="?android:attr/textColorPrimary"
style="@android:style/TextAppearance.Large"
android:layout_below="@+id/cv_product_title"/>
<TextView
android:id="@+id/tv_product_rating"
android:layout_
android:layout_
android:layout_marginStart="10dp"
android:textColor="?android:attr/textColorPrimary"
style="@android:style/TextAppearance.Large"
android:layout_below="@+id/cv_product_title"
android:layout_toEndOf="@+id/tv_product_new" />
<TextView
android:id="@+id/tv_product_description"
android:layout_
android:layout_
android:textColor="?android:attr/textColorPrimary"
style="@android:style/TextAppearance.Medium"
android:layout_below="@+id/tv_product_rating" />
</RelativeLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
【问题讨论】:
【参考方案1】:您应该将 RecyclerView 初始化代码放在 onViewCreated 中。代码很难阅读,但错误表明 tv_product_title 是在项目的相应布局 xml 中定义的。
【讨论】:
你的意思是所有与RecyclerView相关的代码吗? 是的,那么您在方法参数列表中就有了视图。但是没有找到 TextView 的主要问题。也许您有多个用于不同 API 级别的文件。或者你拼错了 id.. 可以在这里添加xml吗? 是androidx没关系。我无法发现您的问题,但令人怀疑的是为什么您在卡片视图和线性布局“@+id/cv_product”中具有相同的 ID。在 Kotlin 中不需要 find view by id 的另一个一般性评论。通常,当您有不同的视图类型和 xml 时,请为它们使用不同的视图持有者。 TextView 应该在 ViewHolder 类中膨胀,而不是在 onBindViewHolder 中。当您需要节省内存时,这样做的方式会破坏 recyclerview 的所有目的。 我修复了重复 ID 问题。不幸的是,我还没有看到在 ViewHolder 类中为 TextView 充气的 Kotlin 教程。我一直致力于节省内存。以上是关于尽管已经声明了文本,但 TextView 出现空错误的主要内容,如果未能解决你的问题,请参考以下文章