NullPointerException accessing views in onCreate()

匿名 (未验证) 提交于 2019-12-03 02:08:02

问题:

This is a canonical question for a problem frequently posted on StackOverflow.

I'm following a tutorial. I've created a new activity using a wizard. I get NullPointerException when attempting to call a method on Views obtained with findViewById() in my activity onCreate().

Activity onCreate():

@Override protected void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     setContentView(R.layout.activity_main);      View something = findViewById(R.id.something);     something.setOnClickListener(new View.OnClickListener() { ... }); // NPE HERE      if (savedInstanceState == null) {         getSupportFragmentManager().beginTransaction()                 .add(R.id.container, new PlaceholderFragment()).commit();     } } 

Layout XML (fragment_main.xml):

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:tools="http://schemas.android.com/tools"     android:layout_width="match_parent"     android:layout_height="match_parent"     android:paddingBottom="@dimen/activity_vertical_margin"     android:paddingLeft="@dimen/activity_horizontal_margin"     android:paddingRight="@dimen/activity_horizontal_margin"     android:paddingTop="@dimen/activity_vertical_margin"     tools:context="packagename.MainActivity$PlaceholderFragment" >      <View         android:layout_width="100dp"         android:layout_height="100dp"         android:id="@+id/something" />  </RelativeLayout> 

回答1:

The tutorial is probably outdated, attempting to create an activity-based UI instead of the fragment-based UI preferred by wizard-generated code.

The view is in the fragment layout (fragment_main.xml) and not in the activity layout (activity_main.xml). onCreate() is too early in the lifecycle to find it in the activity view hierarchy, and a null is returned. Invoking a method on null causes the NPE.

The preferred solution is to move the code to the fragment onCreateView(), calling findViewById() on the inflated fragment layout rootView:

@Override public View onCreateView(LayoutInflater inflater, ViewGroup container,     Bundle savedInstanceState) {   View rootView = inflater.inflate(R.layout.fragment_main, container,       false);    View something = rootView.findViewById(R.id.something); // not activity findViewById()   something.setOnClickListener(new View.OnClickListener() { ... });    return rootView; } 

As a side note, the fragment layout will eventually be a part of the activity view hierarchy and discoverable with activity findViewById() but only after the fragment transaction has been run. Pending fragment transactions get executed in super.onStart() after onCreate().



回答2:

Try OnStart() method and just use

View view = getView().findViewById(R.id.something); 

or Declare any View using getView().findViewById method in onStart()

Declare click listener on view by anyView.setOnClickListener(this);



回答3:

Agreed, this is a typical error because people often don't really understand how Fragments work when they begin working on Android development. To alleviate confusion, I created a simple example code that I originally posted on Application is stopped in android emulator , but I posted it here as well.

An example is the following:

public class ContainerActivity extends FragmentActivity implements ExampleFragment.Callback {     @Override     public void onCreate(Bundle saveInstanceState)     {         super.onCreate(saveInstanceState);         this.setContentView(R.layout.activity_container);         if (saveInstanceState == null)         {                             getSupportFragmentManager().beginTransaction()                 .add(R.id.activity_container_container, new ExampleFragment())                 .addToBackStack(null)              .commit();         }         getSupportFragmentManager().addOnBackStackChangedListener(new OnBackStackChangedListener()         {             public void onBackStackChanged()             {                 int backCount = getSupportFragmentManager().getBackStackEntryCount();                 if (backCount == 0)                 {                     finish();                 }             }         });     }      @Override     public void exampleFragmentCallback()     {         Toast.makeText(this, "Hello!", Toast.LENGTH_LONG).show();     } } 

activity_container.xml:

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"     android:layout_width="match_parent"     android:layout_height="match_parent"     android:orientation="vertical" >      <FrameLayout         android:id="@+id/activity_container_container"         android:layout_width="match_parent"         android:layout_height="match_parent" />  </RelativeLayout> 

ExampleFragment:

public class ExampleFragment extends Fragment implements View.OnClickListener {     public static interface Callback     {         void exampleFragmentCallback();     }      private Button btnOne;     private Button btnTwo;     private Button btnThree;      private Callback callback;      @Override     public void onAttach(Activity activity)     {         super.onAttach(activity);         try         {             this.callback = (Callback) activity;         }         catch (ClassCastException e)         {             Log.e(this.getClass().getSimpleName(), "Activity must implement Callback interface.", e);             throw e;         }     }      @Override     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)     {         View rootView = inflater.inflate(R.layout.fragment_example, container, false);          btnOne = (Button) rootView.findViewById(R.id.example_button_one);         btnTwo = (Button) rootView.findViewById(R.id.example_button_two);         btnThree = (Button) rootView.findViewById(R.id.example_button_three);          btnOne.setOnClickListener(this);         btnTwo.setOnClickListener(this);         btnThree.setOnClickListener(this);         return rootView;     }      @Override     public void onClick(View v)     {         if (btnOne == v)         {             Toast.makeText(getActivity(), "One.", Toast.LENGTH_LONG).show();         }         else if (btnTwo == v)         {             Toast.makeText(getActivity(), "Two.", Toast.LENGTH_LONG).show();         }         else if (btnThree == v)         {             callback.exampleFragmentCallback();         }     } } 

fragment_example.xml:

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"         android:layout_width="match_parent"         android:layout_height="match_parent" >          <Button             android:id="@+id/example_button_one"             android:layout_width="match_parent"             android:layout_height="wrap_content"             android:layout_alignParentTop="true"             android:layout_centerHorizontal="true"             android:layout_marginTop="30dp"             android:text="@string/hello"              android:layout_marginLeft="20dp"             android:layout_marginRight="20dp"/>          <Button             android:id="@+id/example_button_two"             android:layout_width="wrap_content"             android:layout_height="wrap_content"             android:layout_alignLeft="@+id/example_button_one"             android:layout_alignRight="@+id/example_button_one"             android:layout_below="@+id/example_button_one"             android:layout_marginTop="30dp"             android:text="@string/hello" />          <Button             android:id="@+id/example_button_three"             android:layout_width="wrap_content"             android:layout_height="wrap_content"             android:layout_alignLeft="@+id/example_button_two"             android:layout_alignRight="@+id/example_button_two"             android:layout_below="@+id/example_button_two"             android:layout_marginTop="30dp"             android:text="@string/hello" />  </RelativeLayout> 

And that should be a valid example, it shows how you can use an Activity to display a Fragment, and handle events in that Fragment. And also how to communicate with the containing Activity.



回答4:

Try to shift your accessing views to the onViewCreated method of fragment because sometimes when you try to access the views in onCreate method they are not rendered at the time resulting null pointer exception.

 @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {     super.onViewCreated(view, savedInstanceState);      View something = findViewById(R.id.something);      something.setOnClickListener(new View.OnClickListener() { ... }); // NPE HERE       if (savedInstanceState == null) {            getSupportFragmentManager().beginTransaction()             .add(R.id.container, new PlaceholderFragment()).commit();     }  } 


回答5:

The view "something" is in fragment and not in activity, so instead of accessing it in activity you must access it in the fragment class like

In PlaceholderFragment.class

@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View root = inflater.inflate(R.layout.fragment_main, container,   false);  View something = root .findViewById(R.id.something); something.setOnClickListener(new View.OnClickListener() { ... });  return root; } 


回答6:

You are trying to access UI elements in the onCreate() but , it is too early to access them , since in fragment views can be created in onCreateView() method. And onActivityCreated() method is reliable to handle any actions on them, since activity is fully loaded in this state.



回答7:

Since you have declared your View in the fragment_main.xml,move that piece of code where you get the NPE in the onCreateView() method of the fragment. This should solve the issue.



回答8:

Add the following in your activity_main.xml

<fragment     android:id="@+id/myFragment"     android:name="packagename.MainActivity$PlaceholderFragment"     android:layout_width="wrap_content"     android:layout_height="wrap_content" > </fragment> 


回答9:

in the posted code above in the question there is a problem : you are using R.layout.activity_main in oncreate method, but the xml files name is "fragment_main.xml" , means you are trying to get the view of fragment_main.xml file which is not being shown so it gives null pointer exception. change the code like :

@Override protected void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     setContentView(R.layout.fragment_main);// your xml layout ,where the views are      View something = findViewById(R.id.something);     something.setOnClickListener(new View.OnClickListener() { ... }); // NPE HERE      if (savedInstanceState == null) {         getSupportFragmentManager().beginTransaction()                 .add(R.id.container, new PlaceholderFragment()).commit();     } } 


回答10:

You have to remember important thing is : NullPointerException occurs when you have declared your variable and trying to retreive its value before assigning value to it.



回答11:

Use onViewCreated() Method whenever using or calling views from fragments.

override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {     super.onViewCreated(view, savedInstanceState)       View v = view.findViewById(R.id.whatever) } 


回答12:

I've got the same NullPointerException initializing a listener after calling findViewById() onCreate() and onCreateView() methods.

But when I've used the onActivityCreated(Bundle savedInstanceState) {...} it works. So, I could access the GroupView and set my listener.

I hope it be helpful.



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!