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)
Just a hunch, but try inflating your custom View for your ListFragment without using the ViewGroup. So in your ListFragment change
View logv = inflater.inflate(R.layout.listroot, container, false);
to
View logv = inflater.inflate(R.layout.listroot, null);
I have been unable to reproduce your problem with the code you provided, as I do not have any devices that you listed above. My first thought is that it may have something to do with the way you initialize the fragments. Please see my modified nFragmentAdapter
class below. I have changed getItem()
to initialize fragments in a different way:
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();
}
}
And corressponding 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;
}
}
}
Please update on me if this changes anything.
try this.
<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" />
i have replaced android:id="@android:id/list"
with android:id="@+id/android:list"
Don't use android:id="@+id/list" inside ListView . Either You can create id by using one more option i.e android:id="@id/android:list" or you can use android:id="@+id/list1".
thanks for your posts. I was struggling a bit with this as I have just started with Android programming. Changing it to android:id="@android:id/list"
did the trick for me.
Though I have just written a sample program which has only one ListView
that I displayed inside the ListFramgment
, but finally after reading this post I could make it work. Now I am gonna try & see if instead of displaying array of Strings, can I show some custom object (say comprising of a text & icon in one row) in a list.
Thanks much!