getActionview retrun null с Searchview в android [duplicate]

Что такое NullPointerException?

Хорошим местом для начала является JavaDocs . Они охватывают это:

Брошено, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:

  • Вызов метода экземпляра нулевого объекта.
  • Доступ или изменение поля нулевого объекта.
  • Выполнение длины null, как если бы это был массив.
  • Доступ или изменение слотов с нулевым значением, как если бы это был массив.
  • Бросать нуль, как если бы это было значение Throwable.

Приложения должны бросать экземпляры этого класса для указания других незаконных видов использования нулевого объекта.

Также, если вы попытаетесь использовать нулевую ссылку с synchronized, который также выдаст это исключение, за JLS :

SynchronizedStatement:
    synchronized ( Expression ) Block
  • В противном случае, если значение выражения равно null, NullPointerException.

Как это исправить?

Итак, у вас есть NullPointerException. Как вы это исправите? Возьмем простой пример, который выдает NullPointerException:

public class Printer {
    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public void print() {
        printString(name);
    }

    private void printString(String s) {
        System.out.println(s + " (" + s.length() + ")");
    }

    public static void main(String[] args) {
        Printer printer = new Printer();
        printer.print();
    }
}

Идентифицирует нулевые значения

. Первый шаг - точно определить , значения которого вызывают исключение . Для этого нам нужно выполнить некоторую отладку. Важно научиться читать stacktrace . Это покажет вам, где было выбрано исключение:

Exception in thread "main" java.lang.NullPointerException
    at Printer.printString(Printer.java:13)
    at Printer.print(Printer.java:9)
    at Printer.main(Printer.java:19)

Здесь мы видим, что исключение выбрано в строке 13 (в методе printString). Посмотрите на строку и проверьте, какие значения равны нулю, добавив протоколирующие операторы или используя отладчик . Мы обнаруживаем, что s имеет значение null, а вызов метода length на него вызывает исключение. Мы видим, что программа перестает бросать исключение, когда s.length() удаляется из метода.

Трассировка, где эти значения взяты из

Затем проверьте, откуда это значение. Следуя вызовам метода, мы видим, что s передается с printString(name) в методе print(), а this.name - null.

Трассировка, где эти значения должны быть установлены

Где установлен this.name? В методе setName(String). С некоторой дополнительной отладкой мы видим, что этот метод вообще не вызывается. Если этот метод был вызван, обязательно проверьте порядок , что эти методы вызывают, а метод set не будет называться после методом печати. ​​

Этого достаточно, чтобы дать нам решение: добавить вызов printer.setName() перед вызовом printer.print().

Другие исправления

Переменная может иметь значение по умолчанию setName может помешать ему установить значение null):

private String name = "";

Либо метод print, либо printString может проверить значение null например:

printString((name == null) ? "" : name);

Или вы можете создать класс, чтобы name всегда имел ненулевое значение :

public class Printer {
    private final String name;

    public Printer(String name) {
        this.name = Objects.requireNonNull(name);
    }

    public void print() {
        printString(name);
    }

    private void printString(String s) {
        System.out.println(s + " (" + s.length() + ")");
    }

    public static void main(String[] args) {
        Printer printer = new Printer("123");
        printer.print();
    }
}

См. также:

Я все еще не могу найти проблему

Если вы попытались отладить проблему и до сих пор не имеете решения, вы можете отправить вопрос для получения дополнительной справки, но не забудьте включить то, что вы пробовали до сих пор. Как минимум, включите stacktrace в вопрос и отметьте важные номера строк в коде. Также попробуйте сначала упростить код (см. SSCCE ).

140
задан JJD 27 November 2014 в 14:43
поделиться

9 ответов

Наконец, я нашел решение.

  1. Изменение пространства имен actionViewClass с android:actionViewClass до app:actionViewClass
  2. Внедрение интерфейса android.support.v7.widget.SearchView.OnQueryTextListener для текущей активности.
  3. Непосредственно используйте setOnQueryTextListener вместо SearchViewCompat.setOnQueryTextListener
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
      MenuInflater inflater = getMenuInflater();
      inflater.inflate(R.menu.menu, menu);
    
      MenuItem searchItem = menu.findItem(R.id.action_search);
      SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
      if (searchView != null) {
         searchView.setOnQueryTextListener(this);
      }
    
      return super.onCreateOptionsMenu(menu);
    }
    
293
ответ дан Mohsen Afshin 19 August 2018 в 17:12
поделиться
  • 1
    Если это решит вашу проблему, вы, вероятно, должны принять свой ответ. Я также хотел бы указать всем другим людям с похожими проблемами на еще один поток, обсуждая похожие проблемы: stackoverflow.com/q/18407171/1108032 . Если текущий поток не решает ваши проблемы, подумайте о том, чтобы найти там решения. – Boris Strandjev 1 September 2013 в 12:40
  • 2
    Отличный ответ! Может также заплатить, чтобы уточнить, что "приложение" в приложении: actionViewClass также требует дополнительного объявления xmlns для "app & quot; Пространство имен. – jklp 31 October 2013 в 03:35
  • 3
    Необходимо сказать, что класс android.support.v7.widget.SearchView не следует путать с классом android.support.v4.widget.SearchViewCompat (который известен как распространенная ошибка при использовании библиотеки ActionBarCompat) – Alex Semeniuk 11 November 2013 в 11:38
  • 4
    @jklp Я пытаюсь добавить объявление xmlns <menu xmlns:app="http://schemas.android.com/apk/res/android" >, но получить ошибку Attribute is missing the Android namespace prefix. Получаете ли вы это, и как вы это исправите? – anticafe 11 February 2014 в 17:30
  • 5
    Также обратите внимание: android: showAsAction необходимо изменить в app: showAsAction. Также убедитесь, что ваша тема для активности (а не только приложение) ссылается на тему приложения. Последнее, объявление приложения - это « schemas.android.com/apk/res-auto" ; – Kalel Wade 5 March 2014 в 19:23

Вот фрагмент того, как обращаться с SearchView из библиотеки поддержки v7:

@Override
public void onCreateOptionsMenu(final Menu menu,final MenuInflater inflater)
  {
  menu.clear();
  getActivity().getMenuInflater().inflate(...,menu);
  _searchView=(SearchView)MenuItemCompat.getActionView(_searchMenuItem);
  _searchView.setQueryHint(...);

  if(VERSION.SDK_INT<VERSION_CODES.HONEYCOMB)
    {
    final EditText searchTextView=(EditText)searchView.findViewById(R.id.search_src_text);
    if(searchTextView!=null)
      {
      searchTextView.setScroller(new Scroller(_context));
      searchTextView.setMaxLines(1);
      searchTextView.setVerticalScrollBarEnabled(true);
      searchTextView.setMovementMethod(new ScrollingMovementMethod());
      searchTextView.setTextColor(_context.getResources().getColor(App.getResIdFromAttribute(_context,android.R.attr.textColorPrimary)));
      }
    }
  _searchView.setOnQueryTextListener(new android.support.v7.widget.SearchView.OnQueryTextListener()
    {
    ...
    });
  MenuItemCompat.setActionView(_searchMenuItem,_searchView);
  MenuItemCompat.setOnActionExpandListener(_searchMenuItem,new OnActionExpandListener()
    {
    ...
    });
  super.onCreateOptionsMenu(menu,inflater);
  }


public static int getResIdFromAttribute(final Activity activity,final int attr)
  {
  if(attr==0)
    return 0;
  final TypedValue typedvalueattr=new TypedValue();
  activity.getTheme().resolveAttribute(attr,typedvalueattr,true);
  return typedvalueattr.resourceId;
  }

Кроме того, если вы используете Proguard, добавьте это в свою конфигурацию:

-keep class android.support.v4.app.** { *; }
-keep interface android.support.v4.app.** { *; }
-keep class android.support.v7.widget.SearchView { *; }
-keepattributes *Annotation*
0
ответ дан android developer 19 August 2018 в 17:12
поделиться
  • 1
    Для тех, кто хотел отформатировать код, это очень известное форматирование под названием «WhiteSmith». Переход на другой формат не делает его лучше, поскольку это вопрос вкуса. – android developer 27 November 2014 в 14:45
  • 2
  • 3
    @JJD Да. Верный. Это не так часто, как другие, но я использовал его очень долго. Вы можете установить его на Eclipse, если хотите. – android developer 27 November 2014 в 14:53
  • 4
    Спасибо, что поделился. Я остаюсь с дефолтом, так как он избегает много нежелательных обсуждений с членами команды или участниками. – JJD 27 November 2014 в 15:41
  • 5
    @JJD Это тоже правда. в офисе мы работаем немного по-другому, чем по умолчанию. Во всяком случае, хороший разработчик должен иметь возможность обрабатывать все общие стили форматирования, и если он «повреждает глаза», вы всегда можете скопировать код и форматировать его на различные инструменты форматирования (онлайн или на IDE). – android developer 27 November 2014 в 15:50

Удалить код: public class DemoActivity расширяет ActionBarActivity

Заменить на: public class DemoActivity extends Activity

-1
ответ дан Hieu 19 August 2018 в 17:12
поделиться
  • 1
    Зачем ему это делать? Пожалуйста, объясните свой ответ немного подробнее. – Robin Ellerkmann 23 January 2015 в 17:55
  • 2
    Когда я расширяю ActionBarActivity, он всегда возвращает null. Но я расширяю активность только, она работает нормально – Hieu 23 January 2015 в 20:07
  • 3
    Вы должны использовать свое собственное пространство имен при использовании ActionBarActivity, поскольку оно является частью библиотеки поддержки. Поскольку вы используете андроид: showAsAction в своем xml, он работает с Activity (который не из библиотеки поддержки) и не работает с ActionBarActivity – Dennis K 20 April 2015 в 18:44

Ответ Мохсена Афшина выше был моей отправной точкой, и я сделал некоторые настройки, чтобы заставить его работать с моей настройкой:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.menu, menu);
    MenuItem searchItem = menu.findItem(R.id.action_search);
    // SearchView searchView = (SearchView) MenuItemCompat
    //    .getActionView(searchItem);
    SearchView searchView = (SearchView) searchItem.getActionView();
    if (searchView != null) {
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String s) {
                // do something with s, the entered string
                query = s;
                Toast.makeText(getApplicationContext(), 
                    "String entered is " + s, Toast.LENGTH_SHORT).show();
                return true;
            }
            @Override
            public boolean onQueryTextChange(String s) {
                return false;
            }
        });
    }
    return super.onCreateOptionsMenu(menu);
}

menu.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".MainActivity" >

<item android:id="@+id/action_search"
    android:orderInCategory="5"
    android:title="Search"
    android:icon="@drawable/ic_action_search"
    android:showAsAction="ifRoom|collapseActionView"
    android:actionViewClass="android.widget.SearchView" />
</menu>
82
ответ дан JJD 19 August 2018 в 17:12
поделиться
  • 1
    Вау, почему это? Это единственное, что сработало для меня. – Claud 30 November 2015 в 23:11
  • 2
    +1. Довольно очевидно, но я все равно буду упоминать - если вы расширили SearchView до другого класса, сохраните путь к этому классу в proguard! – user2520215 5 April 2016 в 14:29
  • 3
    Работал для меня, исправил мою проблему с крахом на прянике. – neobie 10 November 2016 в 17:13

У меня был тот же код, но вместо использования импорта android.support.v7.widget.SearchView; я использовал import android.widget.SearchView;. Это устранило мою проблему со значением null. Поэтому просто измените этот код в своей активности поиска, и он будет работать, а также изменит пространство имен в XML-файле.

1
ответ дан marcelocolombo 19 August 2018 в 17:12
поделиться
  • 1
    Это была наша проблема, у нас было соединение android.widget.SearchView в Activity, но частичное использование v7 в нашем файле menu_main.xml. Просто убедитесь, что .xml-файл также использует приложение: actionViewClass = & quot; android.support.v7.widget.SearchView & quot; слишком. – gmcc051 18 June 2017 в 03:24

Я думаю, что проблема в том, что вы используете SearchView из пакета поддержки V7, и, возможно, ваш уровень API установлен на ..... 22 ??.

Изменение вашего кода на следующее в для исправления проблемы:

menu.xml

<?xml version="1.0" encoding="UTF-8" ?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
    <item 
        android:id="@+id/action_search"
        android:icon="@drawable/actionbar_button_search"
        android:title="Search"
        android:showAsAction="always"
        android:actionViewClass="android.widget.SearchView" />
</menu> 
5
ответ дан Michele Caggiano 19 August 2018 в 17:12
поделиться
  • 1
    Не могли бы вы объяснить, почему образец кода, который вы предоставили, решает проблему? (Я предполагаю, что так оно и есть.) – anotherNoob 23 June 2018 в 15:44

Для меня проблема с неправильным импортом пространства имен menu.xml вызвала эту проблему.

Мой оригинальный menu.xml:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/tools">
        <item android:id="@+id/action_search"
              android:title="@string/map_option_search"
              android:icon="@drawable/ic_action_search"
              app:showAsAction="collapseActionView|ifRoom"
              app:actionViewClass="android.support.v7.widget.SearchView"/>
</menu>

Похоже, что xmlns:app="http://schemas.android.com/tools" вызывал MenuItemCompat.getActionView(), чтобы вернуться null. Изменение этого импорта в xmlns:app="http://schemas.android.com/apk/res-auto" устранило проблему.

Новая работа menu.xml:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto">
       <item android:id="@+id/action_search"
              android:title="@string/map_option_search"
              android:icon="@drawable/ic_action_search"
              app:showAsAction="collapseActionView|ifRoom"
              app:actionViewClass="android.support.v7.widget.SearchView"/>
</menu>
42
ответ дан Sean Barbeau 19 August 2018 в 17:12
поделиться

У меня была очень похожая проблема с той разницей, что я пытался использовать класс, расширенный android.widget.ImageView

. Если вы используете ProGuard, вам нужно указать, чтобы разрешить методы, задействованные в этом класс.

-keep public class * extends android.widget.ImageView{
  public <init>(android.content.Context);
  public <init>(android.content.Context, android.util.AttributeSet);
  public <init>(android.content.Context, android.util.AttributeSet, int);
  public void set*(...);
}

http://proguard.sourceforge.net/manual/examples.html

Это говорит: «Разрешить все необходимые конструкторы, которые могут быть вызванный из xml и позволяющий использовать любые настраиваемые средства настройки (добавьте больше по мере необходимости) "

0
ответ дан woliveirajr 19 August 2018 в 17:12
поделиться
84
ответ дан JJD 31 October 2018 в 03:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: