getActivity().findViewById返回null,从片段onActivityCreated调用

11 android android-xml android-fragments android-activity

我正在关注有关检索联系人并使用片段显示联系人联系提供者课程.作为参考,我已将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);
}
Run Code Online (Sandbox Code Playgroud)

View mContactsListView是null,意思findViewById是不起作用.

我的父活动是eclipse创建的默认活动.对此,我做了两件事:

  1. 更换import android.app.Activityandroid.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>
Run Code Online (Sandbox Code Playgroud)

匹配活动,以防万一:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

并且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"/>
Run Code Online (Sandbox Code Playgroud)

所以我的问题是,为了findViewById不找到我的观点,我做错了什么?

我尝试过的事情(其中大部分是对几乎看起来像这个问题重复的问题的接受答案):

  • 阅读我逐字逐句复制和粘贴的文件.
  • 试着getView().findViewById()按照这个问题的建议.这也返回null.
  • findViewById(R.id.contacts_list_view);反过来使用这个答案的建议.这不会返回null; 相反,它会导致ClassCastExceptionandroid.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);
    }
    
    Run Code Online (Sandbox Code Playgroud)

    你猜对了 - 仍然是空的.

所以在这一点上我有点失落.我有两个问题:

  1. 我做错了什么(如果我没有提供足够的信息,请在评论中请求其他信息)?
  2. 是否最好将适配器设置保留onAttach在教程中.

the*_*eme 11

我跟随在本教程developer.android.com和所遇到的同样的问题.

最后我注意到这一部分:

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

它似乎试图找到一个View,但传递一个Layout id作为参数.

视图| android参考说:

视图ID在整个树中不一定是唯一的,但最好确保它们在您正在搜索的树的部分中至少是唯一的.

所以,我改变了ListView idcontacts_list_view.xml一个唯一的一个:

<?xml version="1.0" encoding="utf-8"?>
<ListView ...
android:id="@+id/contacts_listview_a_unique_id_here"
... />
Run Code Online (Sandbox Code Playgroud)

然后尝试找到它:

        mContactsList = (ListView) getActivity().findViewById(R.id.contacts_listview_a_unique_id_here);
Run Code Online (Sandbox Code Playgroud)

它的工作原理(在onActivityCreated回调中).

  • 关于强制转换异常:正如hierarchyviewer所示,树是这样的: hierarchyviewer sc 因此,如果您findViewById传递视图的根元素,就像在该帖子中一样,它将返回NoSaveStateFrameLayout,这不是ListView您想要的孩子.