尝试调用虚拟方法 'void android.widget.Button.setOnClickListener(android.view.View$onClickListener)'
attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$onClickListener)'
我正在尝试为按钮实现 LayoutInflater
,但在实现之后出现此错误。我不确定它是否已正确实施。我针对同一个问题尝试了不同的解决方案,但作为 Android 的新手,我发现很难解决这个问题。
https://www.dropbox.com/s/s2k92n6ss4mtztg/Screenrecorder-2020-11-23-00-34-16-139.mp4?dl=0(很抱歉无法解释工作流程,但请参考此剪辑以便更好地理解,第一个 activity 是 IntroductoryActivity,最后一个有开始按钮的是 onboardingfragment3)
请阐明这个问题。谢谢!
IntroductoryActivity.java:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_introductory);
............
**//The button from fragment_on_boarding3**
start_l=findViewById(R.id.startb);
.............
**//Having issue with this part**
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layoutScreen = inflater.inflate(R.layout.fragment_on_boarding3,null);
start_l.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent mainActivity = new Intent(getApplicationContext(),MainActivity.class);
startActivity(mainActivity);
// I need to save a boolean value to storage so next time when the user runs the app,I could know that he has already checked the intro screen activity
// I'm going to use shared preferences forthat process
savePrefsData();
finish();
}
});
}
private boolean restorePrefData() {
SharedPreferences pref = getApplicationContext().getSharedPreferences("myPrefs",MODE_PRIVATE);
Boolean isIntroActivityOpnendBefore = pref.getBoolean("isIntroOpnend",false);
return isIntroActivityOpnendBefore;
}
private void savePrefsData() {
SharedPreferences pref = getApplicationContext().getSharedPreferences("myPrefs",MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
editor.putBoolean("isIntroOpnend",true);
editor.commit();
}
}
OnBoardingFragment3.java:
public class OnBoardingFragment3 extends Fragment {
Context mContext ;
Button start;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
ViewGroup root=(ViewGroup) inflater.inflate(R.layout.fragment_on_boarding3,container,false);
return root;
}
fragment_on_boarding3.xml:
<?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">
<Button android:id="@+id/startb"
android:layout_width="157dp"
android:layout_height="59dp"
android:fontFamily="@font/bungee"
android:text="Let's Start"
android:textSize="15dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.754" />
</androidx.constraintlayout.widget.ConstraintLayout>
错误:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.liq/com.example.liq.IntroductoryActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2946) at....................
findViewById
实际上是这样称呼的:
this.findViewById(someId);
this
指的是 Activity(在你的情况下 IntroductoryActivity
);
来自docs:
Finds a view that was identified by the android:id XML attribute that was processed in onCreate(Bundle).
此 onCreate()
方法是您调用 findViewById
的 Activity 的 onCreate
方法。在您的情况下,该 ID(和视图)属于片段,因此 Activity 无法找到与该 ID 关联的视图,并且 returns null 并且当您想 setOnClickListener
到 start_l
按钮。
您可以在片段的 onViewCreated
方法内将 onClickListener 设置为该按钮:
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
start_l=view.findViewById(R.id.startb);
start_l.setOnClickListener.......
}
编辑:阿里王子的建议也是一种可行的方法,也许是更好的方法。您可以在 onCreateView
:
中初始化视图
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
ViewGroup root=(ViewGroup) inflater.inflate(R.layout.fragment_on_boarding3,container,false);
start_l=root.findViewById(R.id.startb);
start_l.setOnClickListener.......
return root;
}
我也推荐看看这个post
我正在尝试为按钮实现 LayoutInflater
,但在实现之后出现此错误。我不确定它是否已正确实施。我针对同一个问题尝试了不同的解决方案,但作为 Android 的新手,我发现很难解决这个问题。
https://www.dropbox.com/s/s2k92n6ss4mtztg/Screenrecorder-2020-11-23-00-34-16-139.mp4?dl=0(很抱歉无法解释工作流程,但请参考此剪辑以便更好地理解,第一个 activity 是 IntroductoryActivity,最后一个有开始按钮的是 onboardingfragment3)
请阐明这个问题。谢谢!
IntroductoryActivity.java:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_introductory);
............
**//The button from fragment_on_boarding3**
start_l=findViewById(R.id.startb);
.............
**//Having issue with this part**
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layoutScreen = inflater.inflate(R.layout.fragment_on_boarding3,null);
start_l.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent mainActivity = new Intent(getApplicationContext(),MainActivity.class);
startActivity(mainActivity);
// I need to save a boolean value to storage so next time when the user runs the app,I could know that he has already checked the intro screen activity
// I'm going to use shared preferences forthat process
savePrefsData();
finish();
}
});
}
private boolean restorePrefData() {
SharedPreferences pref = getApplicationContext().getSharedPreferences("myPrefs",MODE_PRIVATE);
Boolean isIntroActivityOpnendBefore = pref.getBoolean("isIntroOpnend",false);
return isIntroActivityOpnendBefore;
}
private void savePrefsData() {
SharedPreferences pref = getApplicationContext().getSharedPreferences("myPrefs",MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
editor.putBoolean("isIntroOpnend",true);
editor.commit();
}
}
OnBoardingFragment3.java:
public class OnBoardingFragment3 extends Fragment {
Context mContext ;
Button start;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
ViewGroup root=(ViewGroup) inflater.inflate(R.layout.fragment_on_boarding3,container,false);
return root;
}
fragment_on_boarding3.xml:
<?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">
<Button android:id="@+id/startb"
android:layout_width="157dp"
android:layout_height="59dp"
android:fontFamily="@font/bungee"
android:text="Let's Start"
android:textSize="15dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.754" />
</androidx.constraintlayout.widget.ConstraintLayout>
错误:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.liq/com.example.liq.IntroductoryActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2946) at....................
findViewById
实际上是这样称呼的:
this.findViewById(someId);
this
指的是 Activity(在你的情况下 IntroductoryActivity
);
来自docs:
Finds a view that was identified by the android:id XML attribute that was processed in onCreate(Bundle).
此 onCreate()
方法是您调用 findViewById
的 Activity 的 onCreate
方法。在您的情况下,该 ID(和视图)属于片段,因此 Activity 无法找到与该 ID 关联的视图,并且 returns null 并且当您想 setOnClickListener
到 start_l
按钮。
您可以在片段的 onViewCreated
方法内将 onClickListener 设置为该按钮:
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
start_l=view.findViewById(R.id.startb);
start_l.setOnClickListener.......
}
编辑:阿里王子的建议也是一种可行的方法,也许是更好的方法。您可以在 onCreateView
:
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
ViewGroup root=(ViewGroup) inflater.inflate(R.layout.fragment_on_boarding3,container,false);
start_l=root.findViewById(R.id.startb);
start_l.setOnClickListener.......
return root;
}
我也推荐看看这个post