添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

在android studio中试图引用一个空指针的视图

1 人不认可

stackoverflow!我是安卓开发的新手,我正试图弄清楚安卓中的Fragments。我在 activity_main.xml 中创建了一个 FrameLayout

<FrameLayout
    android:id="@+id/mainFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

而在MainActivity的onCreate方法中,我试图将LoginFragment传递给FrameLayout。下面是MainActivity的代码。

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    showFragment(LoginFragment())
    passwordInput.addTextChangedListener(
        object : TextWatcher {
            override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
            override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
            override fun afterTextChanged(p0: Editable?) {
                logInButton.isEnabled =
                    passwordInput.text.isNotBlank() && loginInput.text.isNotBlank()
    loginInput.addTextChangedListener(
        object : TextWatcher {
            override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
            override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
            override fun afterTextChanged(p0: Editable?) {
                logInButton.isEnabled =
                    passwordInput.text.isNotBlank() && loginInput.text.isNotBlank()
    logInButton.setOnClickListener {
        showFragment(LoginFragment())
private fun showFragment(fragment: Fragment) {
    supportFragmentManager.beginTransaction()
        .replace(R.id.mainFragment, fragment)
        .commit()

LoginFragment的代码。 【替换代码2

还有fragment_login.xml文件。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
    android:id="@+id/loginInput"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginStart="40dp"
    android:layout_marginTop="80dp"
    android:layout_marginEnd="40dp"
    android:autofillHints="username"
    android:hint="@string/enter_login"
    android:inputType="textEmailAddress" />
<EditText
    android:id="@+id/passwordInput"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginStart="40dp"
    android:layout_marginTop="20dp"
    android:layout_marginEnd="40dp"
    android:layout_marginBottom="20dp"
    android:autofillHints="password"
    android:hint="@string/enter_password"
    android:inputType="textPassword" />
<Button
    android:id="@+id/logInButton"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginStart="40dp"
    android:layout_marginEnd="40dp"
    android:enabled="false"
    android:text="@string/log_in" />
</LinearLayout>

I got the null pointer:

原因是: java.lang.NullPointerException。试图对一个空对象引用调用虚拟方法'void android.widget.EditText.addTextChangedListener(android.text.TextWatcher)'。 at com.example.fragmentactivity.MainActivity.onCreate(MainActivity.kt:18)

我真的不明白哪里出了问题。它说我试图引用一个空的视图,但所有这些视图都是viewBinded的,而且在IDE中它们显示的是它们应该有的样子。感谢所有的提示和答案。

android
android-studio
kotlin
KolaYAndr
KolaYAndr
发布于 2022-08-09
2 个回答
cactustictacs
cactustictacs
发布于 2022-08-09
已采纳
0 人赞同

你说的什么意思呢? "视图是视图绑定的" - 你是否在使用 View binding ?还是你在使用(已被废弃的)的 Kotlin synthetic extensions ?因为它看起来像后者

如果你使用的是视图绑定(而且你由于某种原因没有显示自己访问绑定对象),你就必须为 Fragment 的布局创建一个新的绑定对象,因为你是在运行时添加的,它与 MainActivity 的布局XML无关。

如果你使用的是合成扩展,建议是 don't - 它们被弃用是有原因的,最好是转到视图绑定。我不确定这与你添加的布局有什么互动--据我所知,它应该可以工作,但我也知道如果你在一个完全不同的布局中引用一个 View ,它不会抱怨。ID的时候,它不会抱怨,因为它不知道你在编译时到底在做什么。它不能做出任何安全保证,所以IDE没有抱怨的事实并没有告诉你什么,除了 "这些ID存在于某个布局文件中"(建议远离这个扩展的另一个原因)。

如果你不确定 View 的查找是否有效,可以用 findViewById 的老式方法来做。如果视图已经被添加到 Activity 的布局层次中,就会找到它。

至于为什么会发生这种情况--嗯,这里有几件事情不对。

首先你要打电话给 commit() 而不是 commitNow() in your FragmentTransaction :

public abstract int commit()

安排该事务的提交。 提交不会立即发生 它将被安排为主线程上的工作,在该线程下次准备好时进行。

public abstract void commitNow()

同步提交该事务。 任何添加的片段将被初始化,并完全进入其主机的生命周期状态。 而任何被删除的片段将在这个调用返回之前被相应地拆掉。以这种方式提交事务,允许将片段添加为专用的、封装的组件,监测其主机的生命周期状态 同时围绕这些片段完全初始化和准备好的时间提供更坚实的排序保证。管理视图的片段将有那些视图被创建和连接。

基本上,如果你只是调用 commit() Fragment 将被添加到你的 Activity 中。 后来 .你立即试图访问它的视图,但它可能还没有被添加到视图层次结构中。

第二个问题是,要访问 Fragment 上的视图,它必须至少已经到了其生命周期的 onCreateView 阶段,否则就没有视图可供访问。上面的 commitNow() 似乎保证了它将确保 Fragment 在返回时至少处于该阶段,所以视图应该在那里可以访问。