How to handle with "java.lang.NullPointerException: null cannot be cast to non-null type android.widget.TextView"?

huangapple go评论72阅读模式
英文:

How to handle with "java.lang.NullPointerException: null cannot be cast to non-null type android.widget.TextView"?

问题

我是你的中文翻译,以下是你提供的代码部分的翻译:

在Android开发中,我是新手。所以我决定开始制作一个待办事项应用程序。我想要创建一个窗口,用户可以在其中输入任务的标题和描述。在使用Fragment和RecyclerView之后,我开始遇到以下错误:

致命错误:主线程
进程:com.bignerdranch.android.taskmaster,PID:8887
java.lang.RuntimeException:无法启动Activity ComponentInfo {com.bignerdranch.android.taskmaster / com.bignerdranch.android.taskmaster.MainActivity}:java.lang.NullPointerException:无法将null强制转换为非null类型android.widget.TextView

但我无法理解出错的原因。我已经检查了我的MainActivity、Fragment和RecyclerView的适配器。这个错误一直导致我的应用程序停止运行。我将非常感谢您的帮助!

MainActivity.kt

package com.bignerdranch.android.taskmaster

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import com.bignerdranch.android.taskmaster.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    private lateinit var todoAdapter: TodoAdapter
    private lateinit var binding: ActivityMainBinding
    private lateinit var taskViewModel: TaskViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        val tvTodoTitle = findViewById<TextView>(R.id.tvTodoTitle)
        taskViewModel = ViewModelProvider(this).get(TaskViewModel::class.java)

        todoAdapter = TodoAdapter(mutableListOf())
        binding.rvTodoItems.adapter = todoAdapter
        binding.rvTodoItems.layoutManager = LinearLayoutManager(this)

        binding.btnAddTodo.setOnClickListener{
            NewTaskSheet().show(supportFragmentManager,"NewTaskTag")
        }

        taskViewModel.title.observe(this){
            tvTodoTitle.text=String.format("Task:%s",it)
        }
    }
}

NewTaskSheet

package com.bignerdranch.android.taskmaster

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import

<details>
<summary>英文:</summary>

I&#39;m new in android dev. So I decided to start making todo app. I wanted to make a window where a user may enter title and description of his tasks. After using fragment+recycler view I started to get this error: 
FATAL EXCEPTION: main
                                                                                                    Process: com.bignerdranch.android.taskmaster, PID: 8887
                                                                                                    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.bignerdranch.android.taskmaster/com.bignerdranch.android.taskmaster.MainActivity}: java.lang.NullPointerException: null cannot be cast to non-null type android.widget.TextView

But I cannot understand what is wrong. I&#39;ve checked my MainActivity, Fragment and Adapter for recycler view. This error makes my app stop all the time.  I would appreciate your help!

MainActivity.kt

package com.bignerdranch.android.taskmaster

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView
import androidx.lifecycle.ViewModelProvider

import androidx.recyclerview.widget.LinearLayoutManager
import com.bignerdranch.android.taskmaster.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

private lateinit var todoAdapter:TodoAdapter
private lateinit var binding: ActivityMainBinding
private lateinit var taskViewModel: TaskViewModel
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ActivityMainBinding.inflate(layoutInflater)

    setContentView(binding.root)
    val tvTodoTitle = findViewById&lt;TextView&gt;(R.id.tvTodoTitle)
    taskViewModel = ViewModelProvider(this).get(TaskViewModel::class.java)


    todoAdapter = TodoAdapter(mutableListOf())
    binding.rvTodoItems.adapter = todoAdapter
    binding.rvTodoItems.layoutManager = LinearLayoutManager(this)
    binding.btnAddTodo.setOnClickListener{
        NewTaskSheet().show(supportFragmentManager,&quot;NewTaskTag&quot;)
        }
    taskViewModel.title.observe(this){
        tvTodoTitle.text=String.format(&quot;Task:%s&quot;,it)
    }

}

}


NewTaskSheet

package com.bignerdranch.android.taskmaster

import android.os.Bundle

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.ViewModelProvider
import com.bignerdranch.android.taskmaster.databinding.FragmentNewTaskSheetBinding
import com.google.android.material.bottomsheet.BottomSheetDialogFragment

class NewTaskSheet : BottomSheetDialogFragment(){

private lateinit var binding: FragmentNewTaskSheetBinding
private lateinit var taskViewModel: TaskViewModel


override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    binding = FragmentNewTaskSheetBinding.inflate(inflater,container,false)
    // Inflate the layout for this fragment
    return binding.root
}

override fun onViewCreated(view:View,savedInstanceState: Bundle?) {

    super.onCreate(savedInstanceState)
    val activity = requireActivity()
    taskViewModel= ViewModelProvider(activity).get(TaskViewModel::class.java)
    binding.btnSave.setOnClickListener{
        saveAction()
    }

}



private fun saveAction(){
    taskViewModel.title.value=binding.title.text.toString()
    taskViewModel.description.value=binding.description.text.toString()
    binding.title.setText(&quot;&quot;)
    binding.description.setText(&quot;&quot;)
    dismiss()
}

}

TodoAdapter

package com.bignerdranch.android.taskmaster

import android.graphics.Paint.STRIKE_THRU_TEXT_FLAG

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.CheckBox
import android.widget.TextView

import androidx.recyclerview.widget.RecyclerView
import com.bignerdranch.android.taskmaster.databinding.ItemTodoBinding

class TodoAdapter(
private val todos: MutableList<Todo>
):RecyclerView.Adapter<TodoAdapter.TodoViewHolder>() {

class TodoViewHolder( ItemTodoBinding: ItemTodoBinding): RecyclerView.ViewHolder(ItemTodoBinding.root)

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TodoViewHolder {

    val layoutInflater = LayoutInflater.from(parent.context)
    val ItemTodoBinding = ItemTodoBinding.inflate(layoutInflater, parent, false)
    return TodoViewHolder(

        return TodoViewHolder(ItemTodoBinding)
    )


}





private fun toggleStrikeThrough(tvTodoTitle: TextView, isChecked:Boolean){
    if(isChecked){
        tvTodoTitle.paintFlags = tvTodoTitle.paintFlags or STRIKE_THRU_TEXT_FLAG
    }else{
        tvTodoTitle.paintFlags = tvTodoTitle.paintFlags and STRIKE_THRU_TEXT_FLAG.inv()
    }
}

override fun onBindViewHolder(holder: TodoViewHolder, position: Int) {
      val curTodo = todos[position]

      holder.itemView.apply{
          val tvTodoTitle = findViewById(R.id.tvTodoTitle) as TextView
          tvTodoTitle.text = curTodo.title

          val cbDone = findViewById(R.id.cbDone) as CheckBox
          cbDone.isChecked = curTodo.isChecked
          toggleStrikeThrough(tvTodoTitle, curTodo.isChecked)
          cbDone.setOnCheckedChangeListener { _, isChecked -&gt;
              toggleStrikeThrough(tvTodoTitle, isChecked)
              curTodo.isChecked = !curTodo.isChecked


          }

          cbDone.setOnClickListener(View.OnClickListener{

                  todos.removeAll{todo-&gt;
                      todo.isChecked
                  }

                  notifyDataSetChanged()



          })

    }
}

override fun getItemCount(): Int {
      return todos.size
}

}

activity_main

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

&lt;androidx.recyclerview.widget.RecyclerView
    android:id=&quot;@+id/rvTodoItems&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;0dp&quot;
    app:layout_constraintBottom_toTopOf=&quot;@+id/btnAddTodo&quot;
    app:layout_constraintEnd_toEndOf=&quot;parent&quot;
    app:layout_constraintStart_toStartOf=&quot;parent&quot;
    app:layout_constraintTop_toTopOf=&quot;parent&quot; /&gt;


&lt;Button
    android:id=&quot;@+id/btnAddTodo&quot;
    android:layout_width=&quot;wrap_content&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:layout_marginStart=&quot;20dp&quot;
    android:text=&quot;Add&quot;
    app:layout_constraintBottom_toBottomOf=&quot;parent&quot;
    app:layout_constraintEnd_toStartOf=&quot;@+id/btnTodoDone&quot;
     /&gt;

&lt;Button
    android:id=&quot;@+id/btnTodoDone&quot;
    android:layout_width=&quot;wrap_content&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:layout_marginEnd=&quot;8dp&quot;
    android:text=&quot;Done&quot;
    app:layout_constraintBottom_toBottomOf=&quot;parent&quot;
    app:layout_constraintEnd_toEndOf=&quot;parent&quot; /&gt;

</androidx.constraintlayout.widget.ConstraintLayout>

item_todo

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="80dp"
android:paddingStart="8dp"
android:paddingEnd="8dp">

&lt;TextView
    android:id=&quot;@+id/tvTodoTitle&quot;
    android:layout_width=&quot;0dp&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:text=&quot;Example&quot;
    android:textSize=&quot;24sp&quot;
    app:layout_constraintBottom_toBottomOf=&quot;parent&quot;
    app:layout_constraintEnd_toStartOf=&quot;@+id/cbDone&quot;
    app:layout_constraintStart_toStartOf=&quot;parent&quot;
    app:layout_constraintTop_toTopOf=&quot;parent&quot; /&gt;

&lt;CheckBox
    android:id=&quot;@+id/cbDone&quot;
    android:layout_width=&quot;wrap_content&quot;
    android:layout_height=&quot;wrap_content&quot;
    app:layout_constraintBottom_toBottomOf=&quot;parent&quot;
    app:layout_constraintEnd_toEndOf=&quot;parent&quot;
    app:layout_constraintTop_toTopOf=&quot;parent&quot; /&gt;

</androidx.constraintlayout.widget.ConstraintLayout>


P.S The description of this error tells me that it is all in 25 line in MainActivity but I don&#39;t know what is the problem there. Thanks in advance
                                                                                                    	
                                                                                                    	
                                                                                                    &#160;

</details>


# 答案1
**得分**: 1

由于您正在使用View Binding功能,无需使用此行来访问您的TextView:

```kotlin
val tvTodoTitle = findViewById<TextView>(R.id.tvTodoTitle)

当您想要设置标题时,只需执行以下操作:

binding.tvTodoTitle.text = "....."

这假设activity_main 中存在一个名为tvTodoTitle 的TextView。

英文:

As you're using the View Binding feature there's no need to use this line to access your TextView

val tvTodoTitle = findViewById&lt;TextView&gt;(R.id.tvTodoTitle)

When you want to set your Title you can just do

binding.tvTodoTitle.text = &quot;.....&quot;

That's assuming that a TextView with the name tvTodoTitle exists in activity_main

huangapple
  • 本文由 发表于 2023年6月19日 14:47:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/76504224.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定