如何使用cursorloader读取android中的SQLite数据库?

Ter*_*how 32 android android-listview simplecursoradapter android-fragments android-cursorloader

我正在设置我的应用程序,以便人们可以创建他们的朋友组.创建组时,它会将2个表写入SQL数据库.第一个表有一个组名和一个组ID.第二个表有2列,一个组ID和一个用户ID.这工作正常.

但是,现在我希望能够从数据库中读取.我正在使用listview片段,cursorloader但是我无法显示信息.我想列出列表视图中第一个表中的所有组名.

我的问题是,当我第一次使用的cursorloader列出我的联系人,我使用的是Uri来自content provideronCreateLoader方法.特别是我CONTENT_URIContactsContracts.Contacts班上来的.

的例子cursorloadercontentprovider:

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

但是,如果不使用内容提供程序,我不知道该onCreateLoader方法应该放什么,因为在第二个参数中return new CursorLoader(...)需要a Uri.

有关如何在列表视图中显示数据库数据的任何建议?

片段类代码:

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();
    }
}

}
Run Code Online (Sandbox Code Playgroud)

小智 64

Android指南建议ContentProvider您在想要与其他应用程序共享数据时创建.如果你不需要这些,你可以重写方法loadInBackgroud()中的CursorLoader类.例如,在你的下面写这样的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 );
               }
           };
Run Code Online (Sandbox Code Playgroud)

  • 这是我使用的,因为我不需要共享我的数据,我不想重构我的数据库API作为ContentProvider.缺点是没有ContentProvider的东西,我的listviews不会自动知道数据何时发生变化,这是ContentProviders的优点之一.为了解决这个问题,当我知道已经进行了更改时,我重新创建了我的加载器,即不是调用`Cursor.requery()`我现在使用`getLoaderManager().restartLoader(MY_LOADER_ID,null,this);`.这很尴尬,但这是我发现替换`startManagingCursor()`方法的最简单方法. (12认同)

use*_*414 35

这些是在列表片段中创建游标加载器的步骤

1)创建扩展一个类SQLiteOpenHelper并重写onCreate,并onUpgrade以创建表.

2)创建一个扩展类ContentProvider并创建URI以访问您的数据库.请参阅http://developer.android.com/guide/topics/providers/content-providers.html.你的URI添加到URIMatcher您在使用onCreate,onUpdate,查询等(覆盖方法)相匹配的URI.请参阅http://developer.android.com/reference/android/content/UriMatcher.html

3)在insert方法调用中getContext().getContentResolver().notifyChange(uri, null).在查询方法调用setNotificationUri(ContentResolver cr, Uri uri)之前,返回内容提供程序以进行插入更改以自动反映到您的加载程序.(/sf/answers/554058221/).

4)给出该URI onCreateLoader.

注意:如果没有内容提供程序,则从当前的Android版本开始,自动刷新列表的更改是不可行的.如果您不希望看到contentprovider,请将manifest中的exported属性设置为false.或者,您可以在/sf/answers/519564041/中实现自定义CursorLoader,以从数据库中检索数据.但在这种情况下,无法自动刷新数据

  • 感谢您的信息,我会调查一下.我觉得很奇怪,我的选择是使用`ContentProvider`(我不需要)或创建我自己的自定义`CursorLoader`(这似乎是额外的工作)...不会在没有a的情况下查询数据库"内容提供者"是否足够普遍,以至于他们已经想办法在不做额外工作的情况下做到这一点? (9认同)
  • 如果这种类型的数据不会改变呢?我也觉得被迫使用`ContentProvider`很奇怪.是不是有更快/更轻的静态sqlite数据解决方案? (5认同)