修改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
,并且LoaderManager
和CursorLoader
填充了列表视图,所有这些片段都来自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)
答案 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;看看是否可以在列表中显示一些自定义对象(比如包含一行中的文本和图标),而不是显示字符串数组。
非常感谢!