¿Cómo leer una base de datos SQLite en Android con un cursorloader?


Estoy configurando mi aplicación para que las personas puedan crear grupos de sus amigos. Cuando se crea un grupo, escribe 2 tablas en la base de datos SQL. La primera tabla tiene un nombre de grupo y un id de grupo. La segunda tabla tiene 2 columnas, un id de grupo y un id de usuario. Esto está funcionando bien.

Sin embargo, ahora quiero poder leer desde la base de datos. Estoy usando un fragmento de listview con un cursorloader pero estoy teniendo problemas para mostrar la información. Quiero enumerar todos los nombres de grupo de la primera tabla en mi vista de lista.

Mi problema es que, cuando usé por primera vez el cursorloader para listar mis contactos, estaba usando un Uri del content provider en el método onCreateLoader. Específicamente tenía CONTENT_URI de la clase ContactsContracts.Contacts.

Ejemplo de cursorloader con contentprovider:

@Override
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
    Uri contentUri = ContactsContract.Contacts.CONTENT_URI;
    return new CursorLoader(getActivity(),contentUri,PROJECTION,SELECTION,ARGS,ORDER);
}

Sin embargo, sin usar un proveedor de contenido, no se que poner en el método onCreateLoader porque return new CursorLoader(...) requiere un Uri en el segundo argumento.

Cualquier sugerencia sobre cómo podría ser capaz de mostrar mi base de datos ¿datos en un listview?

Código de clase de fragmento:

public class GroupListFragment extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor> {

CursorAdapter mAdapter;
private OnItemSelectedListener listener;
private static final String[] PROJECTION ={GroupContract.GroupDetails.COLUMN_NAME_GROUP_NAME};
private static final String SELECTION = null;
final String[] FROM = {GroupContract.GroupDetails.COLUMN_NAME_GROUP_NAME};
final int[] TO = {android.R.id.text1};
private static final String[] ARGS = null;
private static final String ORDER = null;
private Cursor c;


@Override
public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    mAdapter = new SimpleCursorAdapter(getActivity(), android.R.layout.simple_list_item_1,null,FROM,TO,0 );
    ReadDBAsync readDB = new ReadDBAsync();
    readDB.execute();
}

@Override
public void onActivityCreated(Bundle savedInstanceState){
    super.onActivityCreated(savedInstanceState);
    setListAdapter(mAdapter);
    getLoaderManager().initLoader(0,null,this);
}

@Override
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
    Uri contenturi = Uri.parse("content://preamble.oneapp");
    Uri tableuri = Uri.withAppendedPath(contenturi,GroupContract.GroupDetails.TABLE_NAME);
    return new CursorLoader(getActivity(),tableuri,PROJECTION,SELECTION,ARGS,ORDER);
}

@Override
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
    mAdapter.swapCursor(cursor);
}

@Override
public void onLoaderReset(Loader<Cursor> cursorLoader) {
    mAdapter.swapCursor(null);
}


private class ReadDBAsync extends AsyncTask<Void,Void,String> {

    @Override
    protected String doInBackground(Void... voids) {

        ContractDBHelpers mDBHelper = new ContractDBHelpers(getActivity());
        SQLiteDatabase db = mDBHelper.getReadableDatabase();
        String returnvalue = "database read";
        c = db.query(GroupContract.GroupDetails.TABLE_NAME,PROJECTION,null,null,null,null,null);
        return returnvalue;
    }

    @Override
    protected void onPostExecute(String result){
        Toast.makeText(getActivity(), result, Toast.LENGTH_LONG).show();
    }
}

}
Author: Terence Chow, 2013-08-20

2 answers

Estos son los pasos para crear un cursorloader en un fragmento de lista

1) Cree una clase que extienda SQLiteOpenHelper y anule onCreate y onUpgrade para crear sus tablas.

2) Cree una clase que extienda ContentProvider y cree los URI para acceder a su base de datos. Véase http://developer.android.com/guide/topics/providers/content-providers.html. Agregue sus URI al URIMatcher que usa en onCreate, onUpdate, consulta, etc (métodos reemplazados) para que coincida con el URI. Referir http://developer.android.com/reference/android/content/UriMatcher.html

3) En el método insert llame a getContext().getContentResolver().notifyChange(uri, null). En el método de consulta llame a setNotificationUri(ContentResolver cr, Uri uri) antes de devolver el proveedor de contenido para que el cambio de inserción se refleje automáticamente en su cargador. ( https://stackoverflow.com/a/7915117/936414).

4) Da ese URI en onCreateLoader.

Nota: Sin un proveedor de contenido, la actualización automática de los cambios en la lista no es factible a partir del android actual versión. Si no desea que su contentprovider sea visible, establezca el atributo exportado en manifest en false. O puede implementar su CursorLoader personalizado como en https://stackoverflow.com/a/7422343/936414 para recuperar datos de la base de datos. Pero en este caso la actualización automática de los datos no es posible

 35
Author: user936414,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:09:56

La guía de Android sugiere crear un ContentProvider cuando desee compartir sus datos con otras aplicaciones. Si no necesita esto, puede simplemente anular el método loadInBackgroud() de la clase CursorLoader. Por ejemplo, escribe así en tu onCreateLoader:

return new CursorLoader( YourContext, null, YourProjection, YourSelection, YourSelectionArgs, YourOrder )
           {
               @Override
               public Cursor loadInBackground()
               {
                   // You better know how to get your database.
                   SQLiteDatabase DB = getReadableDatabase();
                   // You can use any query that returns a cursor.
                   return DB.query( YourTableName, getProjection(), getSelection(), getSelectionArgs(), null, null, getSortOrder(), null );
               }
           };
 64
Author: wholeman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-23 11:43:24