无法在kotlin中初始化片段中的按钮

Unable to initialize the button in fragment in kotlin

我正在做一个基本的 android 项目,使用导航控制器和导航主机在单个 activity 中实现片段。在一个片段中,我有两个按钮,我已经在 onCreateView() 方法中用 id 初始化了这两个按钮。但是每当我要 运行 avd 中的应用程序时,应用程序就会崩溃。请帮我解决这个问题。在下面,我将发布有关此问题的所有详细信息:

MainFragment.kt

class MainFragment : Fragment() {

    lateinit var view_balances_button : Button;
    lateinit var pay_someone_button : Button;
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

        val view: View = inflater!!.inflate(R.layout.fragment_main, container, false)

        view_balances_button.findViewById<Button>(R.id.view_balances_button)
        pay_someone_button.findViewById<Button>(R.id.pay_someone_button)

        view_balances_button.setOnClickListener {
            findNavController().navigate(R.id.action_mainFragment_to_viewBalanceFragment2)
        }

        pay_someone_button.setOnClickListener {
            findNavController().navigate(R.id.action_mainFragment_to_viewPeopleFragment2)
        }

        // Inflate the layout for this fragment

        return view
    }

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



    }


}

fragment_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="@dimen/android_default_padding"
    tools:context=".MainFragment">

    <!-- TODO: Update blank fragment layout -->

    <Button
        android:id="@+id/view_balances_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="@string/button_view_balances" />

    <Button
        android:id="@+id/pay_someone_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="@dimen/android_default_padding"
        android:text="@string/button_pay_someone" />

</LinearLayout>

MainActivity.kt

package com.shankhadeep.navigationcomponentjetpack

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.navigation.findNavController
import androidx.navigation.ui.NavigationUI

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

        NavigationUI.setupActionBarWithNavController(this,findNavController(R.id.nav_host_fragment))
    }
}

activty_main.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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">

    <fragment
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/my_navigation"/>

</FrameLayout>

错误信息图片

Error shown in the logcat

在分配给视图的片段 onCreateView View view 中,因此您需要调用 view.findViewById(R.id.yourID)

变化

findNavController().navigate(R.id.action_mainFragment_to_viewBalanceFragment2)

val navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment)

然后使用导航

navController.navigate(R.id.yourNavigation)

修改后的代码

override fun onCreateView(
                inflater: LayoutInflater, container: ViewGroup?,
                savedInstanceState: Bundle?
            ): View? {
        
                val view: View = inflater!!.inflate(R.layout.fragment_main, container, false)
        
                val navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment)

                view_balances_button = view.findViewById(R.id.view_balances_button)
                pay_someone_button = view.findViewById(R.id.pay_someone_button)
        
                view_balances_button!!.setOnClickListener {
                    navController.navigate(R.id.action_mainFragment_to_viewBalanceFragment2)
                }
        
                pay_someone_button!!.setOnClickListener {
                    navController.navigate(R.id.action_mainFragment_to_viewPeopleFragment2)
                }
        
                // Inflate the layout for this fragment
        
                return view
            }

我们在 onCreateView 中遇到一些初始化视图崩溃的问题。

You should inflate your layout in onCreateView but shouldn't initialize other views using findViewById in onCreateView.

因为有时视图没有正确初始化。所以总是在 onViewCreated 中使用 findViewById(当视图完全创建时)并且它还将视图作为参数传递。

onViewCreated 确保视图已完全创建。

onViewCreated android Documentation

onCreateView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle) 返回后,但在任何保存的状态恢复到视图之前立即调用。这让子类有机会在知道自己的视图层次结构已完全创建后进行自我初始化。然而,此时片段的视图层次结构并未附加到其父级。

参考这个stack overflow question
如果我的回答对您有帮助,请通过检查它旁边的✔(勾号)来接受它:)