0

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....................
aditya
  • 3
  • 1
  • 4
  • can you add full error? – Tugay Nov 22 '20 at 18:18
  • You can't use a view from a Fragment in an Activity. Use the button in its fragment otherwise you get an NPE like you do now. – private static Nov 22 '20 at 18:32
  • @Tuqay Following is the 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.................... – aditya Nov 22 '20 at 18:33

2 Answers2

1

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

Tugay
  • 2,057
  • 5
  • 17
  • 32
  • 1
    Or, to follow his fragment, inside onCreateView, use ```View rootView = inflater.inflate(R.layout.fragment_songs , group, false);``` then declare your views: start_l = rootView.findViewById – private static Nov 22 '20 at 18:42
  • @Tuqay , Sir I want to call one of the function of IntroductoryActivity in start_l.setOnClickListener(). That's the reason, I'm trying to set OnClickListener in IntroductoryActivity. – aditya Nov 22 '20 at 18:45
  • what is that function? I am sure there is a way to avoid this – Tugay Nov 22 '20 at 18:50
  • @Tuqay, I've added the functions. Please have a look. – aditya Nov 22 '20 at 19:23
  • @aditya you can copy entire `savePrefsData()` method and paste it in fragment class. Then you would be able to call it. I don't see any problem with that. – Tugay Nov 22 '20 at 19:41
  • @PrinceAli ,Sir I tried your solution with my existing root var, & the application didn't crash this time, but still I got the NPE after clicking on start button. – aditya Nov 23 '20 at 05:27
  • 1
    Edit the question with your updated codes from this answer. You are not doing it correctly. – private static Nov 23 '20 at 12:23
  • 1
    Tuqay , Prince Ali, Thank you very much. By combining both the solutions (Copying **savePrefsData()** in OnBoardingFragment3 & implementing the code proposed by Prince Ali, the app ran successfully. The NPE continued to be there due to absence of **getActivity()** while calling another intent in OnClickButton., but it's solved now. @Prince Ali, can you please answer the question, so that I can mark it as Soved? – aditya Nov 23 '20 at 15:27
  • 1
    Just mark this one if it guided you through and @Tuqay will edit it accordingly. – private static Nov 23 '20 at 15:49
0

I had the same issue.
For me, only the following worked:
Right-click on your activity_main.xml file, click on "Rename file" and change the scope to "Project Files".