【问题标题】:getActivity().findViewById returns null, called from fragment onActivityCreatedgetActivity().findViewById 返回 null,从片段 onActivityCreated 调用
【发布时间】:2013-08-01 20:51:17
【问题描述】:

我正在关注contacts provider lesson on retrieving contacts 并使用片段显示它们。作为参考,我已将 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 为空,表示 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 没有找到我的观点?

我尝试过的事情(其中大部分是对几乎看起来与此问题重复的问题的公认答案):

  • 逐字阅读我复制和粘贴的文档。
  • 按照in this question 的建议尝试getView().findViewById()。这也返回 null。
  • 按照this answer 的建议使用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);
    }
    

    你猜对了 - 仍然为空。

所以在这一点上我有点迷茫。我有两个问题:

  1. 我做错了什么(如果我没有提供足够的信息,请在 cmets 中请求更多信息)?
  2. 是否最好将适配器设置留在onAttach 或教程中说明的位置。

【问题讨论】:

  • 如果您使用的是 Android 框架中的 id,则应将其用作 android.R.id.*TO_IDS 是否定义为 private final static int[] TO_IDS = { android.R.id.text1 }
  • @vikram 是的,它是片段类的成员。

标签: android android-fragments android-activity android-xml


【解决方案1】:

我按照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 作为参数。

View | android reference 说:

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

所以,我将contacts_list_view.xml 中的ListView id 更改为唯一的:

<?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 所示,树是这样的: 所以如果你findViewById 传递视图的根元素,比如that post,它将返回NoSaveStateFrameLayout,这不是你想要的子ListView

【讨论】:

  • 谢谢,我会试一试,让你知道我的进展:)
【解决方案2】:

getActivity().findViewById()Activity 的视图层次结构中查找您作为参数提供的 id。 ListView 可能由片段的onCreateView 返回。如果你想在片段视图层次结构上执行findViewById,你必须调用getView().findViewById()。在这种情况下,由于您正在扩展ListFragment,要检索ListView,至于ListActivity,您必须使用getListView();另一个类比ListActivityListView内部的id xml 文件 (android:id="@android:id/list")

【讨论】:

  • 我知道这是一个老问题,但希望你能为我澄清一些事情。大约一个小时前我问了一个问题,我想我已经通过调用getActivity.findViewById 解决了这个问题,但是我所指的视图是一个片段,这没有意义,这是我的问题的链接- stackoverflow.com/questions/50736715/…
【解决方案3】:

请注意,ListFragment 有一个 getListView() 方法来返回 ListView 小部件实例。

开发者文档:ListFragment.getListView

【讨论】:

    【解决方案4】:

    @theme 提出了一个解决方案,但是这里为了使用android的内部listview是另一种方式。因为在您的“contacts_list_view.xml”文件中,您正在使用 id=@android:id/list 的 android 内部列表视图。在您的代码中,您可以使用 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开发者指南中包含这样的“bug”,这样我们就可以熟悉api了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-29
      • 2019-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-05
      • 2014-04-30
      相关资源
      最近更新 更多