1

First , I know that there are a lot of similar questions asked about that before , but none of them answers my question .

I'll keep it simple .

I have a class called MainActivity which includes the following code :

public class MainActivity extends AppCompatActivity {
    Car myCar = new Car();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
       getSupportFragmentManager().beginTransaction().add(R.id.buttonsContainer,myCar,"me").commitNow();
        View v = myCar.getView(); // returns null
        Button b = v.findViewById(R.id.submitButton); //throws an exception as I'm trying to execute the "findViewById" method on a null object , as the debugger say . 
        b.setText("It works !"); // it doesn't
    }
}

and I have a fragment that includes a single button with the following code :

public class Car extends Fragment {
    View view;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.car, container, false);
        return rootView;
    }
}

It does nothing but showing the layout that corresponds to it.

Here's my MainActivity XML file :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    android:id="@+id/buttonsContainer"
    tools:context="com.example.myapplication.MainActivity">

</LinearLayout>

And here's my fragment XML code :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <Button
        android:id="@+id/submitButton"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button" />
</LinearLayout>

What I am trying to do is basically I want to change the button text when it's clicked to something else (it must happen on the parent activity .

I already know how to do it in the fragment activity ) .

I also want to set an onClickListner to that button from MainActivity and not from the fragment activity itself but whenever I try to access that fragment from the main activity I get null value (doesn't matter whether i'm trying to get a reference to its Activity or View as in myCar.getActivity() or MyCar.getView() ) .

Thanks in advance.

Logcat :

AndroidRuntime: FATAL EXCEPTION: main
 Process: com.example.myapplication, PID: 27060
 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.myapplication/com.example.myapplication.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.view.View.findViewById(int)' on a null object reference
 at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2665)
 at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
 at android.app.ActivityThread.-wrap12(ActivityThread.java)
 at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
 at android.os.Handler.dispatchMessage(Handler.java:102)
 at android.os.Looper.loop(Looper.java:154)
 at android.app.ActivityThread.main(ActivityThread.java:6119)
 at java.lang.reflect.Method.invoke(Native Method)
 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.view.View.findViewById(int)' on a null object reference
 at com.example.myapplication.MainActivity.onCreate(MainActivity.java:23)
 at android.app.Activity.performCreate(Activity.java:6679)
 at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
 at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2618)
 at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726) 
 at android.app.ActivityThread.-wrap12(ActivityThread.java) 
 at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477) 
 at android.os.Handler.dispatchMessage(Handler.java:102) 
 at android.os.Looper.loop(Looper.java:154) 
 at android.app.ActivityThread.main(ActivityThread.java:6119) 
 at java.lang.reflect.Method.invoke(Native Method) 
 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) 
 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
Jason Spake
  • 4,293
  • 2
  • 14
  • 22

3 Answers3

0

Apparently I misunderstood your question. To access a fragment from parent activity the process is similar and this is a way you can achieve that:

MyFragment myFragment;

myFragment = (MyFragment)getSupportFragmentManager().findFragmentByTag("MyFragmentTag");
if(myFragment != null && myFragment.isAdded()) // you need to verify if the instance is actually added to the activity
    myFragment.submitButton.setText("It works");
Ricardo
  • 9,136
  • 3
  • 29
  • 35
  • thanks for the answer , but the point of this question is to have the parent activity modifying if's fragment views , and not vice versa . I want to achieve the same result as the code you've written but without touching the fragment class , all edits should be made to the activity class . Thanks – karl svensson Jun 29 '17 at 13:24
0

Your problem is that when you're creating the fragment in code and adding it the view for the fragment won't be inflated yet so it doesn't exist. If you add Log.v("Trace", "End of onCreate"); at the end of onCreate and Log.v("Trace", "Car view inflated"); inside the onCreateView for the Car fragment you will see this in action. What you should do is change it so the button text gets changed inside the inflation of the fragment view. @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment View rootView = inflater.inflate(R.layout.fragment_car, container, false); Button b = (Button)rootView.findViewById(R.id.submitButton); b.setText("It works !"); return rootView; }

  • You can also add a delegate callback from the fragment after the view is created in the fragment to the main activity if you want to change the text inside that activity instead of inside the fragment view create. – Nathan Romriell Jun 29 '17 at 13:12
  • That's why I used CommitNow , and not commit . – karl svensson Jun 29 '17 at 13:25
  • Please read my comment to @Ricardo to better understand what I'm trying to do (I mentioned that in the question too) – karl svensson Jun 29 '17 at 13:27
  • commitNow() will commit the fragment in a synchronous fashion but doesn't guarantee that the view will be initialized yet. In the android docs it says "initialized and brought completely to the lifecycle state of their host" https://developer.android.com/reference/android/app/FragmentTransaction.html#commitNow() but the host here hasn't finished initialization either. – Nathan Romriell Jun 29 '17 at 13:29
  • I feel like the answers here could help you: https://stackoverflow.com/questions/24188050/how-to-access-fragments-child-views-inside-fragments-parent-activity – Nathan Romriell Jun 29 '17 at 13:35
0

Try below code for Car Fragment

public class Car extends Fragment {
    View view;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        view = inflater.inflate(R.layout.car, container, false);
        return view;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Button b = (Button) view.findViewById(R.id.submitButton); //throws an exception as I'm trying to execute the "findViewById" method on a null object , as the debugger say .
        b.setText("It works !"); // it doesn't
    }
}

And MainActivity like

public class MainActivity extends AppCompatActivity {
    Car myCar = new Car();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getSupportFragmentManager().beginTransaction().add(R.id.buttonsContainer,myCar,"me").commit();
    }
}
Ct9
  • 150
  • 1
  • 11