Java NullPointerException 访问 onCreate() 中的视图
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23653778/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
NullPointerException accessing views in onCreate()
提问by laalto
This is a canonical question for a problem frequently posted on StackOverflow.
这是针对 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 View
s obtained with findViewById()
in my activity onCreate()
.
我正在学习教程。我使用向导创建了一个新活动。我NullPointerException
在尝试调用在我的活动中View
获得的 s上的方法时得到了。findViewById()
onCreate()
Activity onCreate()
:
活动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
):
布局 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>
采纳答案by laalto
The tutorial is probably outdated, attempting to create an activity-based UI instead of the fragment-based UI preferred by wizard-generated code.
该教程可能已经过时,尝试创建基于活动的 UI,而不是向导生成的代码首选的基于片段的 UI。
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.
视图位于片段布局 ( fragment_main.xml
) 而不是活动布局 ( activity_main.xml
) 中。onCreate()
在生命周期中太早,无法在活动视图层次结构中找到它,并null
返回 a。调用方法null
导致 NPE。
The preferred solution is to move the code to the fragment onCreateView()
, calling findViewById()
on the inflated fragment layout rootView
:
首选的解决方案是将代码移动到片段onCreateView()
,调用findViewById()
膨胀的片段布局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()
.
作为旁注,片段布局最终将成为活动视图层次结构的一部分,并且findViewById()
只有在片段事务运行之后才能被活动发现。待处理的片段事务在super.onStart()
之后执行onCreate()
。
回答by Rohit Goyal
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.
既然你已经宣布你在视图fragment_main.xml
,将这段代码你在哪里得到的NPE在onCreateView()
片段的方法。这应该可以解决问题。
回答by EpicPandaForce
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.
同意,这是一个典型的错误,因为人们在开始进行 Android 开发时通常并不真正了解 Fragments 是如何工作的。为了减轻混淆,我创建了一个简单的示例代码,我最初发布在Application is stopped in android emulator 上,但我也将其发布在这里。
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:
<?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:
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.
这应该是一个有效的示例,它展示了如何使用 Activity 来显示 Fragment,并处理该 Fragment 中的事件。以及如何与包含的 Activity 进行通信。
回答by Tarun Sharma
Try OnStart()
method and just use
尝试OnStart()
方法并使用
View view = getView().findViewById(R.id.something);
or Declare any View using getView().findViewById
method in onStart()
或使用getView().findViewById
方法声明任何视图onStart()
Declare click listener on view by anyView.setOnClickListener(this);
在视图上声明单击侦听器 anyView.setOnClickListener(this);
回答by Joyce
Add the following in your activity_main.xml
在您的activity_main.xml 中添加以下内容
<fragment
android:id="@+id/myFragment"
android:name="packagename.MainActivity$PlaceholderFragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</fragment>
回答by Akshay Paliwal
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 :
在上面发布的问题代码中,存在一个问题:您在 oncreate 方法中使用 R.layout.activity_main,但 xml 文件名为“fragment_main.xml”,这意味着您正在尝试获取 fragment_main.xml 文件的视图它没有被显示,所以它给出了空指针异常。更改代码,如:
@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();
}
}
回答by Krishna
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.
您正在尝试访问 中的 UI 元素,onCreate()
但是现在访问它们还为时过早,因为可以在onCreateView()
方法中创建片段视图。并且onActivityCreated()
方法可以可靠地处理对它们的任何操作,因为活动在此状态下已完全加载。
回答by clebertx
I've got the same NullPointerException
initializing a listener after calling findViewById()
onCreate()
and onCreateView()
methods.
NullPointerException
在调用findViewById()
onCreate()
和onCreateView()
方法之后,我有相同的初始化侦听器。
But when I've used the onActivityCreated(Bundle savedInstanceState) {...}
it works. So, I could access the GroupView
and set my listener.
但是当我使用onActivityCreated(Bundle savedInstanceState) {...}
它时它起作用了。所以,我可以访问GroupView
并设置我的监听器。
I hope it be helpful.
我希望它会有所帮助。
回答by Sarthak Sharma
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.
尝试将访问视图转移到片段的 onViewCreated 方法,因为有时当您尝试访问 onCreate 方法中的视图时,它们不会在导致空指针异常的时间呈现。
@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();
}
}
回答by Shubham Goel
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
在 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;
}