Search code examples
layout-inflaterandroid-inflate

attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$onClickListener)'


I'm trying to implement LayoutInflater for a button, but after doing it I'm getting this error. I'm not sure whether it has been implemented correctly or not. I tried different solutions available for the same question, but still, being new to Android, I'm finding it difficult to solve this issue.

https://www.dropbox.com/s/s2k92n6ss4mtztg/Screenrecorder-2020-11-23-00-34-16-139.mp4?dl=0 (I apologize for not able to explain the workflow but please refer this clip for better understanding, the first activity is IntroductoryActivity & the last one where start button is there is onboardingfragment3)

Please shed some light on this problem. Thank You!

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>

Error:

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....................

Solution

  • findViewById is actually is called this:

    this.findViewById(someId);
    

    this refers to Activity (in your case IntroductoryActivity);

    From the docs:

    Finds a view that was identified by the android:id XML attribute that was processed in onCreate(Bundle).

    This onCreate() method is onCreate method of Activity on which you are calling findViewById. In your case, that id (and View) belongs to fragment so Activity is unable to find view associated with that id and returns null and you get NPE when you want to setOnClickListener to start_l button.

    You can set onClickListener to that button inside onViewCreated method of fragment:

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
      super.onViewCreated(view, savedInstanceState);
      start_l=view.findViewById(R.id.startb);
      start_l.setOnClickListener.......
      
    }
    

    Edit: suggestion by Prince Ali is also a possible and maybe better way to do it. You can initialize views inside 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;
    }
    

    I also recommend looking at this post