GetActivity (). FindViewById возвращает null, вызывается из фрагмента onActivityCreated

Я следую уроку для контактов с поставщиками при поиске контактов и их отображении с использованием фрагментов. Для справки, я установил уровень API до 16 (Android 4.1).

Я в основном следовал этому руководству к письму с несколькими заметными исключениями. Например, я импортирую из mypackage.R а не в android.R .

Моя проблема заключается в моем обработчике onActivityCreated в моем ListContactsFragment :

 public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); // Initializes the loader getLoaderManager().initLoader(0, null, this); // Gets the ListView from the View list of the parent activity View mContactsListView = getActivity().findViewById(R.layout.contacts_list_view); mContactsList = (ListView) mContactsListView; // Gets a CursorAdapter mCursorAdapter = new SimpleCursorAdapter( getActivity(), R.layout.contacts_list_item, null, FROM_COLUMNS, TO_IDS, 0); // Sets the adapter for the ListView mContactsList.setAdapter(mCursorAdapter); // Set the item click listener to be the current fragment. mContactsList.setOnItemClickListener(this); } 

View mContactsListView имеет значение null, то есть findViewById не работает.

Моя родительская активность является стандартной по умолчанию, созданной eclipse. Для этого я сделал две вещи:

  1. Замените import android.app.Activity с android.support.v4.app.FragmentActivity чтобы предотвратить исключение ClasscastException , если вы этого не сделаете.
  2. Импортировал фрагмент в XML.

Моя activity_list_contacts.xml выглядит так:

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".ListContactsActivity" > <fragment android:name="mypackage.ListContactsFragment" android:id="@+id/contacts_list_view" android:layout_width="match_parent" android:layout_height="match_parent" /> </RelativeLayout> 

Совместимость, на всякий случай:

 public class ListContactsActivity extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_list_contacts); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.list_contacts, menu); return true; } } 

И contacts_list_view.xml :

 <?xml version="1.0" encoding="utf-8"?> <ListView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="match_parent"/> 

Итак, мой вопрос: что я делаю неправильно для findViewById чтобы не найти свое мнение?

Вещи, которые я пробовал (большинство из них являются принятыми ответами на вопросы, которые почти похожи на дубликат):

  • Читая документ, я скопировал и вставил слово в слово.
  • Попытка getView().findViewById() как предложено в этом вопросе . Это также возвращает null.
  • Используя findViewById(R.id.contacts_list_view); Вместо этого, как это предлагает этот ответ . Это не возвращает null; Вместо этого он вызывает ClassCastException в том, что ClassCastException android.support.v4.app.NoSaveStateFrameLayout не может быть ClassCastException в ClassCastException android.widget.ListView .
  • Я читал, что иногда обратный вызов фрагмента для создания происходит до присоединения к активности. Итак, я добавил обработчик к методу onAttach следующим образом:

     @Override public void onAttach(Activity activity) { super.onAttach(activity); View mContactsListView = activity.findViewById(R.id.contacts_list_view); mContactsList = (ListView) mContactsListView; // Gets a CursorAdapter mCursorAdapter = new SimpleCursorAdapter( getActivity(), R.layout.contacts_list_item, null, FROM_COLUMNS, TO_IDS, 0); // Sets the adapter for the ListView mContactsList.setAdapter(mCursorAdapter); // Set the item click listener to be the current fragment. mContactsList.setOnItemClickListener(this); } 

    Вы догадались – все еще не указана.

Поэтому в этот момент я немного потерялся. У меня есть два вопроса:

  1. Что я делаю неправильно (просьба запросить дополнительную информацию в комментариях, если я не предоставил достаточно)?
  2. onAttach ли оставить настройку адаптера в onAttach или где говорится в учебнике.

Solutions Collecting From Web of "GetActivity (). FindViewById возвращает null, вызывается из фрагмента onActivityCreated"

Я следую учебному курсу на developer.android.com и столкнулся с той же проблемой.

Наконец, я заметил, что в этой части:

 // Gets the ListView from the View list of the parent activity mContactsList = (ListView) getActivity().findViewById(R.layout.contact_list_view); 

Кажется, пытается найти « View , но передать Layout id качестве аргумента.

Просмотр | Ссылка на android говорит:

Идентификаторы просмотра не обязательно должны быть уникальными по всему дереву, но это хорошая практика, чтобы убедиться, что они по меньшей мере уникальны в той части дерева, которое вы ищете.

Итак, я изменил ListView id в ListView id contacts_list_view.xml на уникальный:

 <?xml version="1.0" encoding="utf-8"?> <ListView ... android:id="@+id/contacts_listview_a_unique_id_here" ... /> 

Затем попробуйте найти его с помощью:

  mContactsList = (ListView) getActivity().findViewById(R.id.contacts_listview_a_unique_id_here); 

И он работает (в onActivityCreated ).

  • Об исключении литья: Как показывает иерархический просмотр, дерево выглядит следующим образом: hierarchyviewer СБН Поэтому, если вы NoSaveStateFrameLayout , NoSaveStateFrameLayout передает корневой элемент представления, как в этом сообщении , он вернет NoSaveStateFrameLayout , который не является дочерним ListView вы хотите.

getActivity().findViewById() ищет идентификатор, который вы предоставляете в качестве параметра в иерархии представлений Activity . Вероятно, ListView возвращается onCreateView вашего фрагмента. Если вы хотите выполнить findViewById в иерархии представлений фрагментов, вы должны вызвать getView().findViewById() . В этом случае, поскольку вы расширяете ListFragment , чтобы получить ListView , как и для ListActivity , вы должны использовать getListView(); Другая аналогия с ListActivity – это идентификатор ListView внутри xml-файла ( android:id="@android:id/list" )

Обратите внимание, что ListFragment имеет метод getListView() для возврата экземпляра виджета ListView .

Документы разработчика: ListFragment.getListView

@theme предлагает решение, но для того, чтобы использовать внутренний список Android, это другой способ. Потому что в вашем файле «contacts_list_view.xml» вы используете внутренний список андроида с id = @ android: id / list. И в вашем коде вы можете ссылаться на представление списка с помощью findViewById (android.R.id.list), поэтому ваш onActivityCreated будет выглядеть следующим образом:

 public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); mContactsList = (ListView) getActivity().findViewById(android.R.id.list);//(R.layout.fragment_contact_list); mCursorAdapter = new SimpleCursorAdapter(getActivity(), R.layout.contact_item_list,null, FROM_COLUMNS, TO_IDS, 0); mContactsList.setAdapter(mCursorAdapter); mContactsList.setOnItemClickListener(this); getLoaderManager().initLoader(0,null,this); } 

Надеюсь, это поможет, хорошо, что руководство разработчика Android содержит такую ​​«ошибку», чтобы мы могли быть знакомы с api.