getActivity().findViewById возвращает значение null, вызываемое из фрагмента onActivityCreated
я после contacts provider урок по извлечению контактов и отображение их с помощью фрагментов. Для справки, я установил уровень 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. Для этого я сделал две вещи:--27-->
- заменить
import android.app.Activity
Сandroid.support.v4.app.FragmentActivity
предупрежденияClasscastException
это произойдет, если вы этого не сделаете. - импортировал мой фрагмент в 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
в этойandroid.support.v4.app.NoSaveStateFrameLayout
не может быть приведен к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); }
вы догадались - все равно null.
так что в этот момент я немного потерялся. У меня два вопроса:--27-->
- что я делаю неправильно (пожалуйста, запросите дополнительную информацию в комментариях, если я не предоставил достаточно)?
- предпочтительнее оставить настройку адаптера в
onAttach
, или где говорится в учебнике.
4 ответов
Я следую учебнику по 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
на 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
обратного вызова).
- об исключении cast:
As hierarchyviewer показывает, дерево выглядит так:
так что если вы
findViewById
передача корневого элемента представления, как в этот пост, он вернется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 предложить решение, но для того, чтобы использовать внутренний listview android вот еще один способ. Потому что в вашем " contacts_list_view.xml " файл вы используете внутренний listview android с id=@android:id/list - ... И в вашем коде вы можете обратиться к списку с помощью findViewById (android.R.id.список), поэтому ваш 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.