具有多个ListFragments的Android SherlockFragmentActivity

具有多个ListFragments的Android SherlockFragmentActivity,android,android-fragments,actionbarsherlock,simplecursoradapter,android-loadermanager,Android,Android Fragments,Actionbarsherlock,Simplecursoradapter,Android Loadermanager,我有一个SherlockFragmentActivity,它显示了几个选项卡。每个选项卡都是ListFragment 每个ListFragment都是这样创建的: ActionBar bar = getSupportActionBar(); bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE); bar.setDisplayHome

我有一个SherlockFragmentActivity,它显示了几个选项卡。每个选项卡都是ListFragment

每个ListFragment都是这样创建的:

ActionBar bar = getSupportActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);
bar.setDisplayHomeAsUpEnabled(true);
bar.setDisplayShowTitleEnabled(true);

// users event list
bar.addTab(bar.newTab()
    .setTag("contacts_list")
    .setText(getString(R.string.list_contacts_header))
    .setTabListener(new TabListener<ContactListFragment>(
        this, getString(R.string.list_events_header), ContactListFragment.class, null)));
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    // database cursor containing all venues for this event
    venuesCursor = getDatasource().getAllVenues(((EventActivity) getActivity()).getEventId());

    // hand the cursor to the system to manage
    getActivity().startManagingCursor(venuesCursor);  

    // bind the columns of the cursor to the list
    String[] from = new String[] { VenuesDataSource.KEY_NAME, VenuesDataSource.KEY_DESCRIPTION };
    int[] to = new int[] { R.id.list_item_title, R.id.list_item_subtitle };

    cursorAdapter = new SimpleCursorAdapter(getActivity(), R.layout.list_item, venuesCursor, from, to);

    // retrieve the listview to populate
    ListView lv = (ListView) getActivity().findViewById(android.R.id.list);

    // set the adapter on the listview
    lv.setAdapter(cursorAdapter);

    // click event for each row of the list
    lv.setOnItemClickListener(new OnItemClickListener() {

        public void onItemClick(AdapterView<?> arg0, View view,
                int position, long id) {
            Cursor cursor = cursorAdapter.getCursor();
            cursor.moveToPosition(position);
            Toast.makeText(getActivity(), "Tapped row " + position + "!", Toast.LENGTH_SHORT).show();

        }
    });

    // Start out with a progress indicator.
    setListShown(false);

    // prepare the loader -- either re-connect with an existing one, or start a new one.
    // getLoaderManager().initLoader(0, null, this);

    // load the data
    getActivity().getSupportLoaderManager().initLoader(0, null, this);
}
这是错误的,我使用adb来查看数据库,它抱怨的列100%都在那里,所以这与没有关闭游标或其他东西有关,当上面加载时,它实际上使用了错误的游标

编辑:添加游标加载程序代码

public static final class VenueCursorLoader extends SimpleCursorLoader {

    Context mContext;

    public VenueCursorLoader(Context context) {
        super(context);

        mContext = context;
    }

    @Override
    public Cursor loadInBackground() {
        Cursor cursor = null;
        VenuesDataSource datasource = new VenuesDataSource(mContext);

        // TODO: provide the event_id to the getAllVenues method
        cursor = datasource.getAllVenues(((EventActivity) mContext).getEventId());

        if (cursor != null) {
            cursor.getCount();
        }

        return cursor;
    }

}
非常感谢你的帮助

基本上,你需要了解的一切都在答案中列出了。您应该进行以下几项修复:


  • 您应该首先传递
    CursorAdapter
    a
    null
    光标。
    LoaderManager
    将使用
    CursorLoader
    为您执行初始查询。(见上文我的答案)。还要注意,您当前使用的构造函数是。您应该改为使用(将其作为标志传递
    0

    cursorAdapter=新的SimpleCursorAdapter( getActivity(), R.layout.list_项目, 无效的 从…起 到 0);


  • 删除此行:

    getActivity().startManagingCursor(venuesCursor);
    
    LoaderManager
    的关键在于它为您管理光标。您不需要“将光标交给系统进行管理”。。。这正是装载机管理员的工作:)


  • 由于我在#1和#2中描述的原因,这行代码似乎是不必要的:

    venuesCursor = getDatasource().getAllVenues(
            ((EventActivity) getActivity()).getEventId());
    

  • 我也不知道为什么要覆盖
    onItemClick
    。由于您使用的是
    ListFragment
    s,因此我怀疑您希望覆盖
    onListItemClick

  • 我不知道你为什么要包括这些行,但看起来你也想删除它们

    Cursor cursor = cursorAdapter.getCursor();
    cursor.moveToPosition(position);
    
    在大多数情况下,您不应该操纵适配器的光标,因为它由内部系统管理,并且绑定到
    LoaderManager


谢谢Alex,我将在今天晚些时候进行这些更改,我非常感谢您的帮助——如果答案有效,我会回来接受。为了回答你的“不确定为什么”问题,因为我上周四启动了android开发:)边学边用……如果我删除了你提到的那些项目,列表将如何被通知它应该显示什么?(我还有一个SimpleCursorLoader,也许这是我应该加载数据的时候,而不是在onActivityCreated方法中)好吧,至少你开始走上了正确的道路。。。大多数初学者懒得尝试理解
LoaderManager
的工作原理。(顺便说一句,如果有些东西毫无意义的话,这是完全可以理解的……随着时间的推移,你会越来越习惯的。)不管怎样,你看过了吗?列表知道如何显示数据,因为(1)您已在
光标或适配器上调用了
setListAdapter
(因此它知道将传递给适配器的任何数据与listview关联)。(2)将光标切换到
onload finished
中的
CursorAdapter
(使用
mAdapter.swapCursor(data)
)中。无论采用哪种方式,您都应该提供有关您试图实现的目标、片段之间的关系、每个片段显示的数据类型的更多信息,看起来你的问题更多的是设计问题,而不是如何处理光标的具体问题。在大多数情况下,片段应该彼此独立,因此如果您试图让片段直接重用另一个片段的游标,则不应该这样做。如果你也提出了一个新问题,请将我链接到你的新问题…:)
Cursor cursor = cursorAdapter.getCursor();
cursor.moveToPosition(position);