在主activity的fragment内部,当从FireBase加载数据时,会检查用户是否拥有所有必要的数据,如果没有,则将他发送到所需的activity输入数据。当用户到达所需的活动时,他可以在不同的活动之间切换以输入不同的信息(学校->班级->时间表)
并且由于某种原因,在与学校的活动中,在选择学校时,会弹出一个错误,该错误位于主要活动的片段中。
kotlin.TypeCastException: null cannot be cast to non-null type com.example.kotlindiary.MainActivity
at com.example.kotlindiary.MainFragment$downloadHomework$1$onDataChange$1.onDataChange(MainFragment.kt:210)
抱怨 Intent 初始化的行:
if(timetableisreal){...}
else{
val intent = Intent(activity, SetTimetableActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK.or(Intent.FLAG_ACTIVITY_CLEAR_TASK)
startActivity(intent)
}
我注意到选择学校时会弹出错误,并将错误发送到主片段。我假设 ValueEventListener 多次运行此代码,此时发生错误。但是奇怪的是,在主要活动完成后,监听器继续工作。提前致谢
UPD:片段代码
class MainFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
...
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
...
downloadHomework()
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
super.onCreateOptionsMenu(menu, inflater)
}
fun downloadHomework(){
...
ref.addValueEventListener(object : ValueEventListener{
override fun onDataChange(p0: DataSnapshot) {
user = p0.getValue(User::class.java)
val schoolName = user?.school
val form = user?.form
if(user?.name == "" || user?.surname == ""){//проверка, есть ли имя, фамилия
val intent = Intent(activity, ProfileActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK.or(Intent.FLAG_ACTIVITY_CLEAR_TASK)
startActivity(intent)
(activity as MainActivity).finish()
}
else if(schoolName == ""){//выбрана ли школа
val intent = Intent(activity, ChooseSchoolActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK.or(Intent.FLAG_ACTIVITY_CLEAR_TASK)
startActivity(intent)
(activity as MainActivity).finish()
}
else if(form == ""){//выбран ли класс
val intent = Intent(activity, ChooseFormActivity::class.java)
intent.putExtra("schoolName", schoolName)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK.or(Intent.FLAG_ACTIVITY_CLEAR_TASK)
startActivity(intent)
(activity as MainActivity).finish()
}
else{
val refTimetable = FirebaseDatabase.getInstance().getReference("/schools/$schoolName/$form/timetable")
refTimetable.addValueEventListener(object : ValueEventListener{
override fun onDataChange(p0: DataSnapshot) {
p0.children.forEach {
//проверка, есть ли расписание
}
if(timetableisreal){...}
else{
val intent = Intent(activity, SetTimetableActivity::class.java)//если нет, отправляем на активити с установкой расписания
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK.or(Intent.FLAG_ACTIVITY_CLEAR_TASK)
startActivity(intent)
}
}
override fun onCancelled(p0: DatabaseError) {}
})
}
}
override fun onCancelled(p0: DatabaseError) {}
})
}
}
你的假设被证明是正确的。即使在离开活动之后,远程数据库中更改的侦听器也会继续响应其中的更改。结果,活动在被调用时变为空。
为避免这种情况,您需要明确取消订阅数据库更改。为此,请将您的侦听器保存在一个单独的变量中,并在离开活动之前将其删除。或多或少是这样的: