ListFragment RuntimeException'android.R.id.list'缺失

时间:2013-01-07 22:52:53

标签: android android-listfragment android-fragmentactivity

修改2013年1月16日:问题已解决!两天前,我发布了该应用的更新版本,正确使用ListViews标识了android:id="@android:id/list。实际上,抛出的异常是误导性的,与实际问题无关......

当我实施Sean关于通过将ListFragment传递给null来夸大ViewGroup观看次数的建议时,真正解决了问题。我没有从新版本收到相同的Exception,新版本已被足够的设备下载,以确保此问题得到解决。但是我非常感谢Lawrence的评论和回答,并将继续阅读他如何实例化片段。虽然他提出了将null传递给View inflater的建议,但Sean实际上是第一个这样做的,并且由于他的解决方案似乎已经解决了这个问题,所以奖金将相应地颁发。如果我学习/阅读更多关于实例化片段的不同方法,我会在将来更新这个帖子,正如Lawrence的优秀答案所建议的那样。太糟糕了,我无法分割赏金!

编辑2013年1月14日: ListView相关XML个文件位于http://pastebin.com/2xnG1VfF每个@ LawrenceChoy的请求

修改2013年1月13日:我发布了我的应用的更新版本,并根据碧山的建议使用了android:id="@+id/android:list代替android:id="@android:id/list",不过我是仍然接收我的Fragment Actvity没有a ListView whose id attribute is 'android.R.id.list'的随机例外,即使该活动没有任何ListViews。从LGE手机中添加了另一个例外。

编辑2013年1月9日:虽然碧山提供了答案,但我希望能更多地解释为什么他的解决方案可能会阻止此异常。在进一步阅读之后,我相信这是因为在使用自定义ListView时,应该使用+符号。但是我希望得到确认我是正确的或得到澄清,特别是考虑到两者似乎都适用于许多不同的设备和模拟器。在大约20分钟内筹集赏金以寻求有关此事的信誉良好的来源/答案。感谢。


在最近更新发布到Play商店后,我从一些设备中得到了一些非常奇怪的行为。

在我的新版本中,我有FragmentActivity(称为TabsStyled),它使用FragmentStatePagerAdapter来管理多个片段。我总共有4个片段,其中2个片段扩展ListFragment,并且LoaderManagerCursorLoader填充了列表视图,所有这些片段都来自support.v4个库。其他两个片段没有ListViews,也没有扩展ListFragment

我在多个设备和AVD上进行了大量测试,并且从未遇到任何缺少android.R.id.list的RuntimeExceptions。

然而,一旦发布,一些ACRA崩溃就出现在FragmentAcitivty "Your content must have a ListView whose id attribute is 'android.R.id.list'"上。 TabsStyled.class是管理ListFragments的FragmentActivity,它本身没有任何`ListViews'。这对我来说似乎很奇怪,因为我认为如果要抛出这个异常,它应该是一个ListFragments,而不是" parent" FragmentActivity。

这里是堆栈跟踪的顶部,我很乐意按要求提供任何其他代码或信息,而不是在此处粘贴所有内容。

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.myapp.hiddenforsecurity/com.myapp.hiddenforsecurity.TabsStyled}: 
java.lang.RuntimeException: Your content must have a ListView whose id attribute is 'android.R.id.list'

在这里,pastebin上提供了完整的堆栈跟踪:http://pastebin.com/aiV7pwXP

包含ListViews的每个ListFragments的XML(每个ListView在单独的XML中单独ListFragment):

<ListView android:id="@android:id/list" 
    <!--the release currently uses "@+id/android:list)-->
    android:layout_width="fill_parent" 
    android:layout_height="0dip" 
    android:layout_weight="45" />

上传到pastebin的其中一个ListFragments(略微简化以便更容易诊断)(另一个ListFragment非常相似):http://pastebin.com/Nts3nVx1

略微简化的TabsStyled完整版(FragmentActivity):http://pastebin.com/ZS4Xg8kP

到目前为止创建异常的设备(截至1/14他们继续发布崩溃):

MODEL       BRAND    ANDROID API
GT-I9305    Samsung  4.1.1 (using @android:id/list)
GT-S7562    Samsung  4.0.4 (using @android:id/list)
GalaxyNexus Samsung  4.2.1 (same exception seen with @+id/android:list)
L-01E       LGE      4.0.4 (same exception seen with @+id/android:list)

5 个答案:

答案 0 :(得分:5)

只是预感,但尝试在不使用ViewGroup的情况下为ListFragment充气自定义View。所以在你的ListFragment改变

View logv = inflater.inflate(R.layout.listroot, container, false);

View logv = inflater.inflate(R.layout.listroot, null);

答案 1 :(得分:2)

我无法使用您提供的代码重现您的问题,因为我没有您在上面列出的任何设备。我的第一个想法是它可能与初始化片段的方式有关。请参阅下面我修改过的nFragmentAdapter课程。我已更改getItem()以不同方式初始化片段:

nFragmentAdapter:

class nFragmentAdapter extends FragmentStatePagerAdapter {

        public nFragmentAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override        
        public int getItemPosition(Object object) {
            return POSITION_NONE;
        }

        @Override
        public Fragment getItem(int position) {

            Fragment f = null;
            Bundle args = new Bundle();
            args.putString("content", TabsStyled.CONTENT[position
                    % TabsStyled.CONTENT.length]);
            switch (position) {
            case 0:
                f = Fragment.instantiate(TabsStyled.this,
                        ReviewFragment.class.getName(), args);
                break;
            case 1:
                f = Fragment.instantiate(TabsStyled.this,
                        MyListFragment.class.getName(), args);
                break;
            case 2:
                f = Fragment.instantiate(TabsStyled.this,
                        SmartFragment.class.getName(), args);
                break;
            case 3:
                f = Fragment.instantiate(TabsStyled.this,
                        MyListFragment.class.getName(), args);
                break;
            case 4:
                f = Fragment.instantiate(TabsStyled.this,
                        f.getClass.getName(), args);
                break;
            case 5:
                f = Fragment.instantiate(TabsStyled.this,
                        f.getClass.getName(), args);
                break;
            case 6:
                f = Fragment.instantiate(TabsStyled.this,
                        f.getClass.getName(), args);
                break;
            }
            return f;
        }

        @Override
        public int getCount() {
            return TabsStyled.CONTENT.length;
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return TabsStyled.CONTENT[position % TabsStyled.CONTENT.length].toUpperCase();
        }
    }

并且压制 MyListFragment:

public class MyListFragment extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor> {

        myCursorAdapter mAdapter;
        String orderBy = DBAdapter.activityDateTime + " DESC";

        static final String[] activityQuery = new String[] { DBAdapter.activityRowID, DBAdapter.activityReason, DBAdapter.activityDateTime };

        String content;

    public void refreshView() {
        getLoaderManager().restartLoader(0, null, this);
    }

    @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
                Bundle args = getArguments();
                if(args != null)
                    content = args.getString("content");
                View logv = inflater.inflate(R.layout.listroot, null);
                return logv;           
        }      

        @Override
    public void onActivityCreated(Bundle savedInstanceState) {
                  super.onActivityCreated(savedInstanceState);
                mAdapter = new myCursorAdapter(getActivity(), null);
                setListAdapter(mAdapter);              
                getLoaderManager().initLoader(0, null, this);
        }

        @Override
        public void onListItemClick(ListView l, View v, int position, long id) {
        }

        @Override
        public Loader<Cursor> onCreateLoader(int id, Bundle args) {
                return new CursorLoader(getActivity().getApplicationContext(), myListProvider.activity_URI, activityQuery, null, null, orderBy);
        }

        @Override
        public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
                mAdapter.swapCursor(data);             
        }

        @Override
        public void onLoaderReset(Loader<Cursor> loader) {
                mAdapter.swapCursor(null);     
        }

    public class myCursorAdapter extends CursorAdapter {

        private final LayoutInflater mInflater;

        public myCursorAdapter(Context context, Cursor c) {
                super(context, c, 0);
                mInflater = LayoutInflater.from(context);
        }

        @Override
        public void bindView(View view, Context context, Cursor cursor) {

            TextView logleft = (TextView) view.findViewById(R.id.logleft);
                        logleft.setText(cursor.getString(cursor.getColumnIndex(DBAdapter.activityDateTime)));

            TextView logcenter = (TextView) view.findViewById(R.id.logcenter);
            logcenter.setText(cursor.getString(cursor.getColumnIndex(DBAdapter.activityReason)));

        }

        @Override
        public View newView(Context context, Cursor cursor, ViewGroup parent) {
                View view = null;
                view = mInflater.inflate(R.layout.vlist, parent, false);
            return view;
        }
    }

}

如果这有任何改变,请更新我。

答案 2 :(得分:0)

试试这个。

<ListView android:id="@+id/android:list"
    android:choiceMode="singleChoice" 
    android:paddingTop="4dp" 
    android:paddingBottom="4dp" 
    android:layout_width="fill_parent" 
    android:layout_height="0dip" 
    android:layout_weight="45" />

我已将android:id="@android:id/list"替换为android:id="@+id/android:list"

答案 3 :(得分:0)

不要在ListView中使用android:id =“@ + id / list”。您可以使用另一个选项创建id,即android:id =“@ id / android:list”或者您可以使用android:id =“@ + id / list1”。

答案 4 :(得分:0)

感谢您的帖子。我刚刚开始使用Android编程时,我正在努力解决这个问题。将其更改为android:id="@android:id/list"对我来说很有用。

虽然我刚刚编写了一个示例程序,其中只有一个ListView显示在ListFramgment内,但最后看完这篇文章后我才能使它工作。现在我要试试&amp;看看是否可以在列表中显示一些自定义对象(比如包含一行中的文本和图标),而不是显示字符串数组。

非常感谢!