【问题标题】:Android - NullPointerException on SearchView in Action BarAndroid - 操作栏中 SearchView 上的 NullPointerException
【发布时间】:2013-09-20 21:22:27
【问题描述】:

我在尝试将 SearchView 小部件添加到我的活动中的 ActionBar 时遇到问题 - 在调用 getActionView 以获取我的 SearchView 对象时,我得到了一个空值。

我一直在关注 Android 开发者指南,也浏览了很多 SO 问题以及互联网上的一些其他链接;一切都无济于事。这可能很简单,但我无法弄清楚 - 在我看来,我的代码与谷歌的代码基本相同(除了更改一些名称等),但它仍然无法工作。

任何帮助将不胜感激。

下面是代码的相关位。如果有任何不清楚的地方,请让我知道您是否知道可能出了什么问题。

活动代码:

    private ListView workflowListView;
    private DrawerLayout drawerLayout;
    private ListView drawerList;
    private ActionBarDrawerToggle drawerToggle;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
        setContentView(R.layout.activity_workflow_list);

        workflowListView = (ListView) findViewById(R.id.workflowListView);
        drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawerList = (ListView) findViewById(R.id.drawer_list);

        drawerToggle = new ActionBarDrawerToggle(
             this,                  /* host Activity */
             drawerLayout,         /* DrawerLayout object */
             R.drawable.ic_launcher,  /* nav drawer icon to replace 'Up' caret */
             R.string.app_name,  /* "open drawer" description */
             R.string.app_name  /* "close drawer" description */
             ) {

                /** Called when a drawer has settled in a completely closed state. */
                public void onDrawerClosed(View view) {
    //                getActionBar().setTitle("Closed drawer");
                }

                /** Called when a drawer has settled in a completely open state. */
                public void onDrawerOpened(View drawerView) {
    //                getActionBar().setTitle("Open drawer");
                }
       };

       drawerLayout.setDrawerListener(drawerToggle);
       ActionBar actionBar = getActionBar();
       actionBar.setDisplayShowTitleEnabled(false);

       actionBar.setDisplayHomeAsUpEnabled(true);
       actionBar.setHomeButtonEnabled(true);
       actionBar.setIcon(android.R.color.transparent);

       String[] testData = {"a", "b", "c", "d"};
       ArrayList<String> workflowList = new ArrayList<String>();
           for (String s : testData) {

                workflowList.add(s);
           }

       ArrayAdapter<String> workflowAdapter = new ArrayAdapter<String>(this.getApplicationContext(), R.layout.workflow_list_item, workflowList);

            workflowListView.setAdapter(workflowAdapter);
   }


   @Override
   public boolean onCreateOptionsMenu(Menu menu) {
   // Inflate the menu; this adds items to the action bar if it is present.
        MenuInflater inflater = getMenuInflater();

        inflater.inflate(R.menu.workflow_list, menu);
        inflater.inflate(R.menu.options_menu, menu);

        // Associate searchable configuration with the SearchView
        SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);

        // The below line returned null even though it was used in Google sample code
        SearchView searchView = (SearchView) menu.findItem(R.id.search).getActionView();

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

        return super.onCreateOptionsMenu(menu);
    }

xml/searchable.xml:

<?xml version="1.0" encoding="utf-8"?>

<searchable xmlns:android="http://schemas.android.com/apk/res/android"
        android:label="@string/app_name"
        android:hint="@string/search_hint"
        android:includeInGlobalSearch="false" />

菜单/options_menu.xml:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" 
      xmlns:app="http://schemas.android.com/apk/res-auto" >

    <item android:id="@+id/search"
          android:title="@string/search_title"
          android:icon="@drawable/ic_action_search"
          android:showAsAction="always|collapseActionView"
          android:actionViewClass="android.support.v7.widget.SearchView" />
</menu>

【问题讨论】:

  • 在你的options_menu.xml,你真的需要使用支持库吗?可以试试设置android:actionViewClass="android.widget.SearchView"吗?
  • @jbihan - 嗯,它是应用程序规范所要求的,所以即使我现在删除它,我将来也必须包含它。

标签: android nullpointerexception android-actionbar searchview


【解决方案1】:

尝试将失败的行替换为:

mSearchMenuItem = menu.findItem(R.id.action_search);
mSearchView = (EnglishVerbSearchView) MenuItemCompat.getActionView(mSearchMenuItem);

其中 R.id.action_search 是菜单中搜索项的 ID。

编辑

您的清单应如下所示:

<activity
       android:name="com.bronzelabs.twc.activities.WorkflowListActivity"
       android:label="@string/app_name"
       android:theme="@style/Theme.AppCompat.Light" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>
<activity 
        android:name=".activities.SearchResultActivity"
        android:theme="@style/Theme.AppCompat.Light"
        android:launchMode="singleTop">
        <intent-filter>
            <action android:name="android.intent.action.SEARCH" />
        </intent-filter>
        <meta-data android:name="android.app.searchable" android:resource="@xml/searchable"
            android:value=".activities.SearchResultActivity" />
    </activity>

您拨打setSearchableInfo的方式是:

mSearchView.setSearchableInfo(searchManager.getSearchableInfo(
            new ComponentName(getApplicationContext(), SearchResultActivity.class)));

编辑 2

确保您的菜单 xml 文件是这样的(注意带有 yourapp 命名空间的这 2 个属性 - 当您使用 compat 库时需要这样做):

<menu xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:yourapp="http://schemas.android.com/apk/res-auto" >
    <item android:id="@+id/action_search"
      android:title="@string/action_search"
      android:icon="@drawable/action_search"
      yourapp:showAsAction="always|collapseActionView"
      yourapp:actionViewClass="android.support.v7.widget.SearchView" />
</menu>

【讨论】:

  • 您需要更改 2 个命名空间,在您的情况下它们应该是 app:对于 showAsActionactionViewClass - 请参见上面的示例。熟悉的名字?
  • app 可以是任何东西,在我的示例中是yourapp。它必须指向http://schemas.android.com/apk/res-auto 架构。
  • 那么,看来我需要对 Android 架构进行更多阅读。再次感谢您的帮助,@Szymon :)
  • 非常感谢,我搜索了好几个小时也遇到了问题,但是这个特别编辑解决了我的问题。
  • MenuItemCompat.getActionView() 已被弃用。
【解决方案2】:

在切换到 v21 支持库时,我的发布版本中可能出现了类似的问题,但调试版本中没有。原来是一个混淆问题,并将这一行添加到我的 proguard-rules.txt 文件中修复了它:

-keep class android.support.v7.widget.SearchView { *; }

【讨论】:

    【解决方案3】:

    首先检查您正在为 actionViewClass 使用 app 命名空间。

    android:actionViewClass="android.support.v7.widget.SearchView"-这会引发 NPE

    app:actionViewClass="android.support.v7.widget.SearchView"-使用这个

    第二个

    检查您是否在 menu.xml 和您的 Activity

    中使用 same searchView

    【讨论】:

    • 解决了我的错误,但不是问题的正确答案,呵呵
    【解决方案4】:

    我遇到了一个非常相似的问题,以下行返回 null

    SearchView searchView = (android.support.v7.widget.SearchView)MenuItemCompat.getActionView(searchMenuItem);
    

    修复在我的 styles.xml 文件中,我将 AppTheme 的父级更改为 Theme.AppCompat.Light

    <resources>
        <!-- Base application theme. -->
        <style name="AppTheme" parent="Theme.AppCompat.Light">
    

    【讨论】:

      【解决方案5】:

      对于仍在搜索的任何人,我都按照上面的所有内容进行操作,但似乎无法进行。我将我的 searchView.setSearchableInfo... 包装在一个空检查中,瞧!它运行正常。

      if (searchView != null) {
          searchView.setSearchableInfo(searchManager.getSearchableInfo(
                          new ComponentName(getApplicationContext(), SearchActivity.class)));
      }
      

      【讨论】:

        【解决方案6】:

        对我来说,这是正确的答案: 在 menu/options_menu.xml 中,使用这个:

        app:actionViewClass="android.support.v7.widget.SearchView"
        

        【讨论】:

          【解决方案7】:

          我觉得你在占用FragmentActivity,你需要扩展ActionBarActivity

          【讨论】:

          • 我不确定您的回答是否真的有意义。如果这就是您的意思,该类正在扩展 ActionBarActivity。
          【解决方案8】:

          我遇到了同样的问题。我的解决方案是: 代替 android:actionViewClass="android.support.v7.widget.SearchView"

          android:actionViewClass="android.widget.SearchView"
          

          【讨论】:

          • 对不起伙计,但正如我上面提到的,我需要使用项目规范的支持库。