在片段的onCreateOptionsMenu()中使用getActivity()偶尔会抛出一个NPE

时间:2016-06-08 20:54:16

标签: java android android-fragments

我在我的片段中使用了SearchManager。不幸的是,使用方法调用getActivity()。getSystemService(Context.SEARCH_SERVICE)偶尔会抛出NullPointerException。在仪器化的Espresso单元测试和正常使用期间都会发生这种情况。当我再次运行测试时,一切都很好。你能告诉我怎么解决这个问题吗?谢谢。

堆栈跟踪:

06-05 16:10:59.162 19183 19183 D AndroidRuntime: Shutting down VM
06-05 16:10:59.188 19183 19183 E AndroidRuntime: FATAL EXCEPTION: main
06-05 16:10:59.188 19183 19183 E AndroidRuntime: Process: foo.bar.baz, PID: 19183
06-05 16:10:59.188 19183 19183 E AndroidRuntime: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object android.app.Activity.getSystemService(java.lang.String)' on a null object reference
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at foo.bar.baz.sign_browser.SignBrowserFragment.onCreateOptionsMenu(SignBrowserFragment.java:139)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at android.app.Fragment.performCreateOptionsMenu(Fragment.java:2133)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at android.app.FragmentManagerImpl.dispatchCreateOptionsMenu(FragmentManager.java:1945)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at android.app.Activity.onCreatePanelMenu(Activity.java:2834)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at android.support.v4.app.FragmentActivity.onCreatePanelMenu(FragmentActivity.java:298)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at android.support.v7.view.WindowCallbackWrapper.onCreatePanelMenu(WindowCallbackWrapper.java:85)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at android.support.v7.app.AppCompatDelegateImplBase$AppCompatWindowCallbackBase.onCreatePanelMenu(AppCompatDelegateImplBase.java:241)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at android.support.v7.view.WindowCallbackWrapper.onCreatePanelMenu(WindowCallbackWrapper.java:85)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at android.support.v7.app.ToolbarActionBar.populateOptionsMenu(ToolbarActionBar.java:443)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at android.support.v7.app.ToolbarActionBar$1.run(ToolbarActionBar.java:60)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at android.os.Handler.handleCallback(Handler.java:739)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:95)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at android.os.Looper.loop(Looper.java:135)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:5343)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at java.lang.reflect.Method.invoke(Method.java:372)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:905)
06-05 16:10:59.188 19183 19183 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:700)
06-05 16:10:59.227 835 1557 I WindowManager: Screen frozen for +393ms due to AppWindowToken{19c5842b token=Token{34cb447a ActivityRecord{10afa8a5 u0 foo.bar.baz/.activities.MainActivity t4133}}}
06-05 16:10:59.233 835 1557 W ActivityManager: Force finishing activity 1 foo.bar.baz/.activities.MainActivity

SignBrowserFragment.onCreateOptionsMenu()

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    Log.d(TAG, "onCreateOptionsMenu " + hashCode());
    inflater.inflate(R.menu.options_sign_browser, menu);
    final MenuItem item = menu.findItem(R.id.action_toggle_starred);
    if (this.showStarredOnly) {
        item.setIcon(R.drawable.ic_sign_browser_grade_checked);
    } else {
        item.setIcon(R.drawable.ic_sign_browser_grade);
    }
    final SearchManager searchManager = (SearchManager) getActivity().getSystemService(Context.SEARCH_SERVICE);
    final MenuItem searchItem = menu.findItem(R.id.action_search);
    final SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
    searchView.setSearchableInfo(searchManager.getSearchableInfo(getActivity().getComponentName()));
}

我使用SignBrowserFragment,它包含在MainActivity中,为搜索添加选项菜单项。实际搜索在单独的SignSearch活动中执行。

清单文件:

    <activity
        android:name=".activities.MainActivity"
        android:theme="@style/AppTheme.NoActionBar">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>

        <meta-data
            android:name="android.app.default_searchable"
            android:value=".sign_browser.search.SignSearchActivity" />
    </activity>
    <activity
        android:name=".sign_browser.search.SignSearchActivity"
        android:parentActivityName=".activities.MainActivity"
        tools:ignore="UnusedAttribute">
        <intent-filter>
            <action android:name="android.intent.action.SEARCH" />
        </intent-filter>

        <meta-data
            android:name="android.app.searchable"
            android:resource="@xml/searchable" />
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value=".activities.MainActivity" />
    </activity>

如果您需要更多信息,请与我们联系。

编辑:为什么这被标记为&#34;如何修复NullPointerException&#34;?这与将其标记为&#34;如何修复错误&#34;的复制一样明智。 :(

编辑2:对不起,伙计们。正如我刚刚意识到我为onCreateOptionsMenu方法发布了错误的代码。我的代码片段来自SignSearchActitivity。唯一真正的区别在于,在调用getSystemService之前调用片段getActivity()。所以getActivty()返回null。为什么 occassionaly 发生在片段的onCreateOptionsMenu()方法中?

3 个答案:

答案 0 :(得分:0)

问题在于

searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));

如果对象为null(意味着getSystemService(Context.SEARCH_SERVICE);返回了一个空对象),该怎么办?它会抛出NPE,对吧。

将您的代码更改为:

 if(searchManager != null){
      searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
    }
else{
     // Can't perform the search because of null object message to the user (or) log (or) console.
    }

答案 1 :(得分:0)

我认为您正面临此错误,因为您正在从片段调用活动,即使它未创建。您应该在执行onActivityCreated()函数之后或期间调用getActivity(),该函数会通知创建活动。从onCreate()方法调用OnCreateOptionsMenu(),因此可能不会在该时间点创建您的活动。 有关详细信息,请参阅此链接 https://developer.android.com/guide/components/fragments.html

答案 2 :(得分:-1)

你忘了打电话给super.onCreateOptionsMenu(..)

  

@Override public void onCreateOptionsMenu(菜单菜单,MenuInflaterinflater){

Log.d(TAG, "onCreateOptionsMenu " + hashCode());

super.onCreateOptionsMenu(menu, inflater);

inflater.inflate(R.menu.options_sign_browser, menu);
final MenuItem item = menu.findItem(R.id.action_toggle_starred);

if (this.showStarredOnly) {
    item.setIcon(R.drawable.ic_sign_browser_grade_checked);
} else {
    item.setIcon(R.drawable.ic_sign_browser_grade);
}

final SearchManager searchManager = (SearchManager) getActivity().getSystemService(Context.SEARCH_SERVICE);

final MenuItem searchItem = menu.findItem(R.id.action_search);

final SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
searchView.setSearchableInfo(searchManager.getSearchableInfo(getActivity().getComponentName()));
     

}