导致致命异常的意外生命周期?

Unexpected lifecycle causing Fatal Exception?

我是一名 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 不是 'injected'。查看堆栈跟踪后,我确定这可能是在调用 bindLocation() 之前未调用 onViewCreated() 的结果。

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

非常感谢您的帮助!

来自我的 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);

现在我想我明白了问题所在。

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

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

请尝试在 onViewCreated() 调用 super 后调用 bindLocation()

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

在你使用这个库之前你必须做一些配置 ButterKnife Eclipse Configuration 或者 ButterKnife Android Studio Configuration

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