0

Edit 1/16/2013: Problem Resolved! Two days ago, I released an updated version of the app and correctly identified the ListViews as I had originally done, by using android:id="@android:id/list. Really though, the exception being thrown was misleading and that had nothing to do with the actual problem...

The real fix came when I implemented the suggestions by Sean on inflating the ListFragment views by passing null to the ViewGroup. I have not received the same Exception from the new version, and the new version has been downloaded by enough devices to safely say this issue is resolved. However I really appreciate the comments and answer made by Lawrence, and will continue to read about how he is instantiating the Fragments. While he provided the suggestion of passing null to the View inflater, Sean was actually the first to do so, and since his solution seems to have resolved the issue, the bounty will be awarded accordingly. I will update this thread in the future if I learn/read more about the different ways of instantiating the Fragments as suggested by Lawrence's excellent answer. Too bad I can't split the bounty!

Edit 1/14/2013: ListView related XML files are located at http://pastebin.com/2xnG1VfF per @LawrenceChoy's request

Edit 1/13/2013: I released an updated version of my app and used android:id="@+id/android:list instead of android:id="@android:id/list" per Bishan's suggestion, however I am still receiving random exceptions that my Fragment Actvity does not have a ListView whose id attribute is 'android.R.id.list', even though that activity does not have any ListViews. Added another exception from LGE phone.

Edit 1/9/2013: Although Bishan provided an answer, I was hoping for a little more explanation as to why his solution might prevent this exception. After reading further I believe it is because when using a custom ListView, one should use a + symbol. However would like to get confirmation I am correct or to get clarification, especially considering both seem to work on many different devices and emulators. Raising a bounty in about 20 minutes to seek a reputable source/answer on the matter. Thanks.


I'm getting some very odd behavior from a few devices out in the wild after a recent updated release to the play store.

In my new release I have a FragmentActivity (called TabsStyled) that uses a FragmentStatePagerAdapter to manage several fragments. I have a total of 4 fragments, and 2 of those fragments extend ListFragment and have listviews populated by LoaderManager and CursorLoader, all from support.v4 libraries. The other two fragments do not have ListViews and do not extend ListFragment.

I did extensive testing on multiple devices as well as AVDs and never encountered any RuntimeExceptions for missing android.R.id.list.

However, upon release, a few ACRA crashes showed up for the FragmentAcitivty "Your content must have a ListView whose id attribute is 'android.R.id.list'". TabsStyled.class is the FragmentActivity that manages the ListFragments and itself does not have any `ListViews'. This seems very strange to me, since I would think that if this exception were to be thrown, it should be for one of the ListFragments, and not the "parent" FragmentActivity.

Here's the top of the stack trace, and I'm happy to provide any additional code or info as requested rather than paste everything here.

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'

A full stack trace available on pastebin here: http://pastebin.com/aiV7pwXP.

The XML for each of the ListFragments which contain the ListViews (a separate ListView in a separate XML for each 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" />

One of the ListFragments (slightly simplified to make this easier to diagnose) uploaded to pastebin (the other ListFragment is very similar): http://pastebin.com/Nts3nVx1

And a slightly simplified full version of TabsStyled (FragmentActivity): http://pastebin.com/ZS4Xg8kP

The devices that created the exceptions thus far (and as of 1/14 they continue to post crashes):

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)
4

5 回答 5

5

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

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

View logv = inflater.inflate(R.layout.listroot, null);
于 2013-01-14T17:32:43.817 回答
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;
        }
    }

}

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

于 2013-01-15T04:05:02.753 回答
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"

于 2013-01-08T04:24:41.910 回答
0

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

于 2013-01-15T04:45:30.240 回答
0

谢谢你的帖子。当我刚开始使用 Android 编程时,我在这方面有点挣扎。将其更改为android:id="@android:id/list"对我有用。

虽然我刚刚编写了一个示例程序,其中只有一个ListView显示在ListFramgment. 现在我要尝试看看是否可以在列表中显示一些自定义对象(比如在一行中包含一个文本和图标),而不是显示字符串数组。

非常感谢!

于 2013-05-12T21:33:59.983 回答