【问题标题】:Unexpected lifecycle causing Fatal Exception?意外的生命周期导致致命异常?
【发布时间】:2015-06-25 02:16:47
【问题描述】:

我是一名 iOS 开发人员,完全没有使用 Android 的经验,如果我在表达我的问题时遇到困难,请见谅:

我在负责维护的 Android 应用程序中遇到致命异常。

Fatal Exception: java.lang.RuntimeException Unable to start activity ComponentInfo{…}: java.lang.NullPointerException

我可以从崩溃报告(附在下面)中看到,崩溃发生在我的一个片段中的一个名为“bindLocation”的方法中

这是它崩溃的行:

            mLocationHeaderTextView.setVisibility(View.VISIBLE);

很明显,问题在于 mLocationHeaderTextview 为空。 mLocationHeaderTextView 使用 roboguice 注入如下:

 @InjectView(R.id.filter_location_header)
TextView mLocationHeaderTextView;

现在,我认为错误是由于我的 textView 没有被“注入”造成的。查看堆栈跟踪后,我确定这可能是 onViewCreated() 在调用 bindLocation() 之前没有被调用的结果。

然而,这就是我迷路的地方。我对android非常不熟悉,所以我不确定我的onViewCreated方法怎么可能被跳过。我已经在设备上尝试了一百万种方法来尝试重现这种情况,但我做不到。无论我想尝试什么用户操作,我的 onViewCreated 方法都会被调用,并且我的变量是非 Null。也许我误读了堆栈跟踪。我希望我下面的堆栈跟踪为你们提供了足够的信息来帮助我,但如果没有,请告诉我关于该应用程序我还能告诉你什么。我不能发布我的完整源代码(因为它不属于我),但我会提供我能提供的任何信息。

非常感谢您的帮助!

来自我的 FilterDrawerFragment:

 @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_filter_drawer, container, false);

    ButterKnife.inject(this, view);

    return view;
}

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    mRulesHeaderReset.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            resetRules();
        }
    });

    if (getActivity() != null && mDrawerLayout == null) {
        mDrawerLayout = (DrawerLayout) getActivity().findViewById(R.id.filter_drawer_layout);

        if (mDrawerLayout != null) {
            mDrawerLayout.setDrawerListener(new DrawerLayout.DrawerListener() {
                @Override
                public void onDrawerSlide(View view, float v) {

                }

                @Override
                public void onDrawerOpened(View view) {
                    NavigationUtils.invalidateOptionsMenu(getActivity());
                }

                @Override
                public void onDrawerClosed(View view) {
                    notifyFiltersChanged();

                    NavigationUtils.invalidateOptionsMenu(getActivity());
                }

                @Override
                public void onDrawerStateChanged(int i) {

                }
            });

            // set a custom shadow that overlays the main content when the drawer opens
            mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.END);
        }
    }

    mlocationChangeButton.setOnClickListener(this);

    bindUI();
}

 private void bindUI() {
    if (isAdded() && mConfiguration != null) {

        // bind the location
        bindLocation();
        …
    }
}

private void bindLocation() {
    if (isAdded() && mConfiguration != null && mConfiguration.isLocationEnabled()) {

        // show the location related items
        mLocationHeaderTextView.setVisibility(View.VISIBLE);//Crash reported here.
        …
            }
        });

    }
}


/**
 * Users of this fragment must call this to update the filter configuration
 */
public void updateConfiguration(FilterConfiguration configuration) {
    if (configuration != null && !configuration.equals(mConfiguration)) {
        mConfiguration = configuration;

        bindUI();
    }
}

并且 updateConfiguration() 被调用 LocationFinderFragment:

 @Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    if (getArguments() != null) {
          ………
    if (savedInstanceState == null) {
        mFilterDrawerFragment = FilterDrawerFragment.newInstance();
        getChildFragmentManager()
                .beginTransaction()
                .replace(R.id.filter_drawer, mFilterDrawerFragment)
                .commit();

    } else {
        mFilterDrawerFragment = (FilterDrawerFragment) getChildFragmentManager().findFragmentById(R.id.filter_drawer);
    }

    ………         
);
    …………………
    populateFilters();
}


private void populateFilters() {
    // these might be passed into the fragment
    if (mFacets != null) {
        FilterConfiguration config = new FilterConfiguration() {{
        ……………………
        }};

        mFilterDrawerFragment.updateConfiguration(config);

【问题讨论】:

  • 试试 if(mLocationHeaderTextView!=null)mLocationHeaderTextView.setVisibility(View.VISIBLE);让我知道这是否能解决问题。
  • 我知道如何检查空变量,但我并没有真正试图解决这个变量为空的事实,我试图了解导致它的原因空。
  • 我假设它在您尝试保留状态时崩溃?
  • 不确定。我自己无法重现崩溃。主线程堆栈跟踪的最后一行是:android.app.ActivityThread.performLaunchActivity (ActivityThread.java:2394)
  • 抱歉误解了您的最后陈述。我没有意识到您无法重现崩溃。

标签: android nullpointerexception crash roboguice


【解决方案1】:

这就是我解决这个问题的方法。当您使用 ButterKnife 时。 如果没有这些配置,ButterKnife 会抛出 NPE

在使用此库之前,您必须对ButterKnife Eclipse ConfigurationButterKnife Android Studio Configuration

如果您正在使用 ADT 并且缺少 Annototion 处理检查此安装Android Eclipse - Cannot see annotation processing option

【讨论】:

    【解决方案2】:

    现在我想我看到了问题。

    1. 在 roboguice 视图中注入 onViewCreated()
    2. onViewCreated()onCreateView() 之后调用。
    3. bindLocation()onCreateView() 中调用。

    因此,此时 roboguice 尚未注入视图。

    请在拨打super 后尝试在onViewCreated() 中拨打bindLocation()

    【讨论】:

    • 我在上面的问题中添加了我的 onCreateView() 和 onViewCreated() 方法。在 onViewCreated() 中调用 bindLocations
    • 所以你也在同一个项目中使用了butterknife?在这种情况下,哪个库将您的视图注入片段中?我想说一个注入库一开始就太多了,但是两个具有相同的注释名称...... textview 上使用了谁的@InjectView?
    • 如果由我决定,我不会使用任何注入库,但我正在接管这个(非常大的)项目,所以我别无选择。无论如何,@injectView 是 ButterKnife。我在上面添加了更多代码。希望对您有所帮助!
    • @Ragnar,好的,现在更清楚了,所以另一个片段在我们的片段上调用了一个需要创建布局的方法。我们的片段已创建,但在执行时没有布局,这就是 NPE 存在的原因。
    • @RagnarDanneskjöld 嘿,我正在考虑这条线 if (savedInstanceState == null),这是我的新嫌疑人。您能否尝试在 if 块之后移动替换事务,以便无论如何都会发生?我说的是以getChildFragmentManager()...开头的4行。
    猜你喜欢
    • 2014-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多