如何从CursorLoader刷新光标?

时间:2020-12-21 08:40:22

So I have my MainDisplayActivity which implements both Activity and LoaderManager.LoaderCallbacks<Cursor>. Here I have A ListView, which I fill with Agenda information that I get from my database using a ContentProvider. I also have a GridView which is a calendar. I have it set up when clicking a cell, that the agenda is updated with the day clicked. My problem is that when reusing the Loader I created in onCreate() inside of the setOnItemClickListener(), it does not refresh the information with the new cursor I am creating. I can just create a new Loader with another ID, and it works once, but once I click another day, it stops refreshing. The problem, lies in the cursor. How can I refresh a cursor from a Loader so I don't have to keep creating a new Loader? Thanks in advance!

所以我有我的MainDisplayActivity,它实现了Activity和LoaderManager.LoaderCallbacks 。在这里,我有一个ListView,我填写了我使用ContentProvider从我的数据库获得的议程信息。我还有一个GridView,它是一个日历。我点击一个单元格时设置了它,在点击的那一天更新议程。我的问题是,当重用我在setOnItemClickListener()内部的onCreate()中创建的Loader时,它不会使用我正在创建的新游标刷新信息。我可以用另一个ID创建一个新的Loader,它可以工作一次,但是一旦我点击另一天,它就会停止刷新。问题在于光标。如何从Loader刷新游标,这样我就不必继续创建新的Loader?提前致谢!

Initial call to create the Loader in onCreate() in My MainDisplayActivity class:

初始调用在My MainDisplayActivity类的onCreate()中创建Loader:

makeProviderBundle(new String[] {"_id, event_name, start_date, start_time, end_date, end_time, location"},
            "date(?) >= start_date and date(?) <= end_date", new String[]{getChosenDate(), getChosenDate()}, null);
    getLoaderManager().initLoader(0, myBundle, MainDisplayActivity.this);

    list.setAdapter(agendaAdapter);

These are the overridden methods from LoaderCallbacks<Cursor>

这些是来自LoaderCallbacks 的重写方法

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    Uri baseUri = SmartCalProvider.CONTENT_URI;
    return new CursorLoader(this, baseUri, args.getStringArray("projection"), 
            args.getString("selection"), args.getStringArray("selectionArgs"), args.getBoolean("sortOrder") ? args.getString("sortOrder") : null );
}



@Override
public void onLoadFinished(Loader<Cursor> arg0, Cursor arg1) {
    agendaAdapter.swapCursor(arg1);
}



@Override
public void onLoaderReset(Loader<Cursor> arg0) {
    //Not really sure how this works. Maybe I need to fix this here?
    agendaAdapter.swapCursor(null);

}

public void makeProviderBundle(String[] projection, String selection, String[] selectionArgs, String sortOrder){
    /*this is a convenience method to pass it arguments 
     * to pass into myBundle which in turn is passed 
     * into the Cursor loader to query the smartcal.db*/
    myBundle = new Bundle();
    myBundle.putStringArray("projection", projection);
    myBundle.putString("selection", selection);
    myBundle.putStringArray("selectionArgs", selectionArgs);
    if(sortOrder != null) myBundle.putString("sortOrder", sortOrder);
}

Any additional code needed please do not hesitate to ask. Thanks again for any help!

如果需要任何其他代码,请不要犹豫。再次感谢任何帮助!

1 个解决方案

#1


40  

You just need to move your code around a little and call restartLoader. That is,

您只需稍微移动代码并调用restartLoader即可。那是,

  1. When the user clicks a list item, you somehow change the private instance variable that is returned in getChosenDate() (I am being intentionally vague here because you didn't specify what exactly getChosenDate() returns).

    当用户单击列表项时,您会以某种方式更改在getChosenDate()中返回的私有实例变量(我在这里故意模糊,因为您没有指定getChosenDate()返回的确切内容)。

  2. Once the change is made, call getLoaderManager().restartLoader() on your Loader. Your old data will be discarded and restartLoader will trigger onCreateLoader to be called again. This time around, getChosenDate() will return a different value (depending on the list item that was clicked) and that should do it. Your onCreateLoader implementation should look something like this:

    完成更改后,在Loader上调用getLoaderManager()。restartLoader()。您的旧数据将被丢弃,并且restartLoader将触发onCreateLoader再次被调用。这一次,getChosenDate()将返回一个不同的值(取决于被单击的列表项),并且应该这样做。你的onCreateLoader实现应该是这样的:

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        Uri baseUri = SmartCalProvider.CONTENT_URI;
    
        makeProviderBundle(
            new String[] { "_id, event_name, start_date, start_time, end_date, end_time, location" },
            "date(?) >= start_date and date(?) <= end_date", 
            new String[]{ getChosenDate(), getChosenDate() }, 
            null);
    
        return new CursorLoader(
                this, 
                baseUri, 
                args.getStringArray("projection"), 
                args.getString("selection"), 
                args.getStringArray("selectionArgs"),    
                args.getBoolean("sortOrder") ? args.getString("sortOrder") : null);
    }
    

Let me know if that makes sense. :)

如果这有意义,请告诉我。 :)

#1


40  

You just need to move your code around a little and call restartLoader. That is,

您只需稍微移动代码并调用restartLoader即可。那是,

  1. When the user clicks a list item, you somehow change the private instance variable that is returned in getChosenDate() (I am being intentionally vague here because you didn't specify what exactly getChosenDate() returns).

    当用户单击列表项时,您会以某种方式更改在getChosenDate()中返回的私有实例变量(我在这里故意模糊,因为您没有指定getChosenDate()返回的确切内容)。

  2. Once the change is made, call getLoaderManager().restartLoader() on your Loader. Your old data will be discarded and restartLoader will trigger onCreateLoader to be called again. This time around, getChosenDate() will return a different value (depending on the list item that was clicked) and that should do it. Your onCreateLoader implementation should look something like this:

    完成更改后,在Loader上调用getLoaderManager()。restartLoader()。您的旧数据将被丢弃,并且restartLoader将触发onCreateLoader再次被调用。这一次,getChosenDate()将返回一个不同的值(取决于被单击的列表项),并且应该这样做。你的onCreateLoader实现应该是这样的:

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        Uri baseUri = SmartCalProvider.CONTENT_URI;
    
        makeProviderBundle(
            new String[] { "_id, event_name, start_date, start_time, end_date, end_time, location" },
            "date(?) >= start_date and date(?) <= end_date", 
            new String[]{ getChosenDate(), getChosenDate() }, 
            null);
    
        return new CursorLoader(
                this, 
                baseUri, 
                args.getStringArray("projection"), 
                args.getString("selection"), 
                args.getStringArray("selectionArgs"),    
                args.getBoolean("sortOrder") ? args.getString("sortOrder") : null);
    }
    

Let me know if that makes sense. :)

如果这有意义,请告诉我。 :)