访问onCreate()中的视图的NullPointerException

时间:2014-05-14 11:44:43

标签: java android android-fragments nullpointerexception

这是针对StackOverflow上经常发布的问题的规范性问题。

我正在关注教程。我使用向导创建了一个新活动。尝试在我的活动NullPointerException中使用View获取的findViewById()上的方法时,我得到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();
    }
}

布局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>

13 个答案:

答案 0 :(得分:69)

本教程可能已过时,尝试创建基于活动的UI,而不是向导生成的代码首选的基于片段的UI。

视图位于片段布局(fragment_main.xml)中,而不在活动布局中(activity_main.xml)。 onCreate()在生命周期中过早,无法在活动视图层次结构中找到它,并返回null。在null上调用方法会导致NPE。

首选解决方案是将代码移至片段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;
}

作为旁注,片段布局最终将成为活动视图层次结构的一部分,并且可以通过活动findViewById()发现,但仅在片段事务运行之后才能发现。待处理的片段事务在super.onStart()之后onCreate()执行。

答案 1 :(得分:10)

尝试 OnStart() 方法,然后使用

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

或使用 getView().findViewById

中的onStart()方法声明任何视图

通过anyView.setOnClickListener(this);

在视图上声明点击监听器

答案 2 :(得分:3)

尝试将访问视图转移到片段的onViewCreated方法,因为有时当您尝试访问onCreate方法中的视图时,它们不会在此时呈现,从而导致空指针异常。

ErrorDocument 100  /public/index.php/err/err
#or https://www.domainname.biz/public/index.php/err/err

答案 3 :(得分:2)

同意,这是一个典型的错误,因为人们在开始开发Android开发时经常不了解Fragments的工作方式。为了减轻混淆,我创建了一个我最初在Application is stopped in android emulator上发布的简单示例代码,但我也在这里发布了。

以下是一个例子:

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>

这应该是一个有效的例子,它展示了如何使用Activity来显示Fragment,并处理该Fragment中的事件。以及如何与包含活动进行通信。

答案 4 :(得分:2)

您正在尝试访问@foreach($Project->ProjectSkills as $ProjectSkill) @if($Skill->SkillID == $ProjectSkill->SkillID) <option selected value="{{$Skill->SkillID}}">{{$Skill->Skill}}</option> @else <option value="{{$Skill->SkillID}}">{{$Skill->Skill}}</option> @endif @break; @endforeach 中的UI元素,但现在访问它们还为时过早,因为在片段视图中可以使用onCreate()方法创建。 onCreateView()方法可以处理对它们的任何操作,因为活动在此状态下完全加载。

答案 5 :(得分:2)

视图“某事”是片段而不是活动,所以不是在活动中访问它,而是必须在片段类中访问它,如

在PlaceholderFragment.class

a {
 color: #FFF;
 text-decoration: none;
 font-weight: bold;
 position: relative;
}

nav a:hover:after {
    content: "";
    display: block;
    border: 8px solid #405580;
    border-bottom-color: #fff;
    position: absolute;
    left:33%;
    margin-top: 5px;
}

答案 6 :(得分:1)

activity_main.xml

中添加以下内容
<fragment
    android:id="@+id/myFragment"
    android:name="packagename.MainActivity$PlaceholderFragment"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" >
</fragment>

答案 7 :(得分:0)

由于您已在fragment_main.xml中声明了视图,因此请在片段的onCreateView()方法中移动您获得NPE的代码段。 这应该可以解决问题。

答案 8 :(得分:0)

在问题上面的发布代码中存在问题: 您在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();
    }
}

答案 9 :(得分:0)

我在调用NullPointerException findViewById()onCreate()方法后初始化了一个监听器onCreateView()

但是当我使用onActivityCreated(Bundle savedInstanceState) {...}时,它可以工作。所以,我可以访问GroupView并设置我的听众。

我希望它有所帮助。

答案 10 :(得分:0)

你必须记住重要的是: 当您声明变量并尝试在为其赋值之前检索其值时,会发生NullPointerException。

答案 11 :(得分:0)

在使用或调用片段中的视图时,使用 onViewCreated()方法。

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

答案 12 :(得分:0)

最受欢迎的库,用于查找几乎每个开发人员都使用的视图。

ButterKnife

尽管如此,他们的答案足以解释用适当的方法找到观点。但是如果你经常每天都是android开发人员和代码,那么你可以使用黄油刀,这样可以节省很多时间来查找视图而且你没有编写代码,只需2-3步即可找到视图以毫秒为单位。

在app level gradle中添加依赖关系:

implementation 'com.jakewharton:butterknife:8.8.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'

添加黄油刀插件

File -> Settings -> plugins-> 

然后搜索 Android ButterKnife Zelezny 并安装插件并重新启动工作室,您就完成了它。

现在只需转到您的活动的Oncreate方法并右键单击您的layout_name并点击生成按钮并选择butterknife注入选项,您的视图引用将自动创建,如下所示:

    @BindView(R.id.rv_featured_artist)
    ViewPager rvFeaturedArtist;
    @BindView(R.id.indicator)
    PageIndicator indicator;
    @BindView(R.id.rv_artist)
    RecyclerView rvArtist;
    @BindView(R.id.nsv)
    NestedScrollingView nsv;
    @BindView(R.id.btn_filter)
    Button btnFilter;