Loader <cursor> onCreateLoader(int,Bundle)是否与Fragment Lifecycle相关? ListView没有填充

时间:2015-09-04 00:55:03

标签: android android-fragments android-studio android-contentprovider loader

就像标题一样,当{是Loader<Cursor> onCreateLoader(int, Bundle)被调用与片段生命周期有关时?我正在尝试实现由Content Provider支持的CursorLoader来填充片段内的ListView。创建片段时,列表视图不会填充,但是当我退出活动时(通过启动另一个intent)并返回带有CursorLoader的片段(导致再次查询Content Provider),列表视图将按预期填充。 / p>

这使我怀疑我的初始化和/或查询顺序不正确。在我的Content Provider查询方法中,我调用cursor.setNotificationUri(contentResolver, uri)并在insert语句中调用getContext().getContentResolver().notifyChange(uri, null)

非常感谢任何帮助!

的ContentProvider

public class VenueProvider extends ContentProvider {
public static final String TAG = "VenueProvider";

DatabaseHelper databaseHelper;

public static final String AUTHORITY = "com.androidtitan.hotspots.Provider.VenueProvider";
public static final String BASE_PATH = DatabaseHelper.TABLE_VENUES;

public static String base_CONTENT_URI = "content://" + AUTHORITY
        + "/" + BASE_PATH + "/";



//MIME Types for getting a single item or a list of them

public static final String VENUES_MIME_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE
        + "/vnd.com.androidtitan.Data.venues";
public static final String VENUE_MIME_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE
        + "/vnd.com.androidtitan.Data.venues";

//Column names
public static class InterfaceConstants {
    public static final String id = "_id";
    public static final String venue_name = "venue_name";
    public static final String venue_city = "venue_city";
    public static final String venue_category = "venue_category";
    public static final String venue_id_string = "venue_string";
    public static final String venue_rating = "venue_rating";
}

//URI matcher variable
private static final int GET_ALL = 0;
private static final int GET_ONE = 1;
private static final int GET_SELECT = 2;

static UriMatcher uriMatcher = BuildUriMatcher();

static UriMatcher BuildUriMatcher() {

    UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);

    //Uri to match and the code to return when matched

    matcher.addURI(AUTHORITY, BASE_PATH, GET_ALL);
    matcher.addURI(AUTHORITY, BASE_PATH + "/#", GET_ONE);
    matcher.addURI(AUTHORITY, BASE_PATH + "/*", GET_SELECT);

    return matcher;
}

@Override
public boolean onCreate() {

    databaseHelper = DatabaseHelper.getInstance(getContext());
    return true;
}

@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {

    Cursor queryCursor;

    switch(uriMatcher.match(uri)) {
        case GET_ALL:

            queryCursor = databaseHelper.getReadableDatabase().rawQuery("SELECT * FROM "
                    + DatabaseHelper.TABLE_VENUES, null);
            break;

        case GET_ONE:

            queryCursor = databaseHelper.getReadableDatabase().rawQuery("SELECT * FROM "
                    + DatabaseHelper.TABLE_VENUES
                    + " WHERE " + DatabaseHelper.KEY_ID + " = " + uri.getLastPathSegment(), null);
            break;

        case GET_SELECT:

            String selectionQuery = "SELECT * FROM " + DatabaseHelper.TABLE_VENUES + " td, "
                    + DatabaseHelper.TABLE_COORDINATES + " tg, " + DatabaseHelper.TABLE_COORDINATES_VENUES
                    + " tt WHERE tg." + DatabaseHelper.KEY_LOCAL + " = ? AND tg." + DatabaseHelper.KEY_ID
                    + " = " + "tt." + DatabaseHelper.KEY_COORDS_ID + " AND td." + DatabaseHelper.KEY_ID
                    + " = " + "tt." + DatabaseHelper.KEY_VENUES_ID;

            Log.e(TAG, "selectionQuery: " + selectionQuery);
            queryCursor = databaseHelper.getReadableDatabase().rawQuery(selectionQuery,
                    new String[] { String.valueOf(uri.getLastPathSegment()) });
            break;

        default:
            throw new IllegalArgumentException("Unknown Uri:" + uri);
    }

    // Tell the cursor what uri to watch, so it knows when its source data changes
    queryCursor.setNotificationUri(getContext().getContentResolver(), uri);
    return queryCursor;

}

@Override
public String getType(Uri uri) {
    switch(uriMatcher.match(uri)) {

        case GET_ALL:
            return VENUES_MIME_TYPE;
        case GET_ONE:
            return VENUE_MIME_TYPE;
        case GET_SELECT:
            return VENUES_MIME_TYPE;
        default:
            throw new IllegalArgumentException("Unknown uri: " + uri);
    }
}

@Override
public Uri insert(Uri uri, ContentValues values) {
    int uriType = uriMatcher.match(uri);
    SQLiteDatabase database = databaseHelper.getWritableDatabase();

    long insertId = 0;
    switch(uriType) {
        case GET_ONE:

            insertId = database.insert(DatabaseHelper.TABLE_VENUES, null, values);

            break;

        case GET_ALL:
            break;

        case GET_SELECT:
            break;

        default:
            throw new IllegalArgumentException("Unknown URI: " + uri);
    }

    Log.e(TAG,"KEY_ID " + uri.getLastPathSegment()
            + " KEY_LOCATION_ID " + values.getAsLong(DatabaseHelper.KEY_VENUE_LOCATION_ID));

    databaseHelper.assignVenueToLocation(Long.valueOf(uri.getLastPathSegment()),
            values.getAsLong(DatabaseHelper.KEY_VENUE_LOCATION_ID));


    getContext().getContentResolver().notifyChange(uri, null);
    return uri;
    //return Uri.parse(DatabaseHelper.TABLE_VENUES + "/" + insertId);

}

//todo:::
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {

    return 0;
}

@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
    int uriType = uriMatcher.match(uri);
    SQLiteDatabase database = databaseHelper.getWritableDatabase();

    int updateId = 0;

    switch(uriType) {
        case GET_ONE:

            updateId = database.update(DatabaseHelper.TABLE_VENUES, values, null, null);

            break;

        case GET_ALL:
            break;

        case GET_SELECT:
            break;

        default:
            throw new IllegalArgumentException("Unknown URI: " + uri);
    }

    getContext().getContentResolver().notifyChange(uri, null);
    return updateId;
}

}

初始化Loader的片段

public class VenueResultsFragment extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor> {
private static final String TAG = "VenueResultsFragment";

DatabaseHelper databaseHelper;

LocationBundle focusLocation;
//    String locationName;
int locationIndex;

private static final String[] PROJECTION = new String[]{
        VenueProvider.InterfaceConstants.id,
        VenueProvider.InterfaceConstants.venue_name,
        VenueProvider.InterfaceConstants.venue_city,
        VenueProvider.InterfaceConstants.venue_category,
        VenueProvider.InterfaceConstants.venue_id_string,
        VenueProvider.InterfaceConstants.venue_rating};

private static final int LOADER_ID = 1;

private LoaderManager.LoaderCallbacks<Cursor> callBacks;
private SimpleCursorAdapter adapter;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    databaseHelper = DatabaseHelper.getInstance(getActivity());

    locationIndex = getArguments().getInt(MapsActivity.venueFragmentLocIndex);
    focusLocation = databaseHelper.getAllLocations().get(locationIndex);

    if (databaseHelper.getAllVenuesFromLocation(focusLocation).size() == 0) {
        new FoursquareHandler(getActivity(), focusLocation.getLatlng().latitude,
                focusLocation.getLatlng().longitude, locationIndex);
    }


    String[] dataColumns = {VenueProvider.InterfaceConstants.venue_name};
    int[] viewItems = {R.id.nameTextView};

    adapter = new SimpleCursorAdapter(getActivity(), R.layout.listview_venue_item, null,
            dataColumns, viewItems, 0);

    setListAdapter(adapter);

    callBacks = this;

    LoaderManager lm = getLoaderManager();
    lm.initLoader(LOADER_ID, null, callBacks);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View v = inflater.inflate(R.layout.fragment_venue_results, container, false);


    return v;
}

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    try {
        //mListener = (OnFragmentInteractionListener) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString()
                + " must implement Interface");
    }
}

@Override
public void onDetach() {
    super.onDetach();
    //mListener = null;
}

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {

    Log.e(TAG, "pre-cursorLoader locationName: " + focusLocation.getLocalName());

    return new CursorLoader(getActivity(), Uri.parse(VenueProvider.base_CONTENT_URI + focusLocation.getLocalName()),
            PROJECTION, null, null, null);
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
    // switch (loader.getId()) {
    //case LOADER_ID:
    // break;
    // }
    adapter.swapCursor(cursor);
}

@Override
public void onLoaderReset(Loader<Cursor> loader) {

    adapter.swapCursor(null);
}

}

1 个答案:

答案 0 :(得分:0)

所以事实证明我遇到的问题是我查询不好。事情很好,我修好了。

我阅读了这篇文章,它为我做了直截了当的事:How does CursorLoader with LoaderManager know to send the cursor to a CursorAdapter?

要回答我的问题,尽管在调用内容提供程序时会创建内容提供程序,这将是scanAreaView!.boundsgetLoaderManager.initLoader()然后填充Loader,然后Loader将信息传递给适配器。

如果我错了,有人可以纠正我或添加一些东西吗?