不推荐使用SimpleCursorAdaptor。我发现这对我来说不是理想的选择,因为它使用UI线程,并且我将显示数百条记录。我想使用一些使用后台线程的东西。经过一番研究,我遇到了CursorLoader。我一直在看教程,但发现实施起来确实很棘手。如果有更好的替代CursorLoader的方法,请告诉我。请有人帮我。我到目前为止的代码。是:

public void getListFromDb(){
    Cursor res = myDb.ViewAll();
    startManagingCursor(res);


    //Map cursor from db to viewFields
    String[] fromFieldNames = new String[]{DatabaseHelper.COL_2, DatabaseHelper.COL_3, DatabaseHelper.COL_4, DatabaseHelper.COL_5};
    int[] toViewIDS = new int[]{R.id.viewName, R.id.viewAddress, R.id.viewPostcode, R.id.viewType};

    //Create adaptor to map items from DB to UI
    SimpleCursorAdapter myCursorAdaptor = new SimpleCursorAdapter(this, R.id.item_layout, res, fromFieldNames, toViewIDS);

    // Set adaptor for listView
    ListView myList = (ListView) findViewById(R.id.listViewLocations);
    myList.setAdapter(myCursorAdaptor);

}

最佳答案

实际上,只描述了一个SimpleCursorAdapter构造函数,而不是整个类。您仍然可以使用它,但是必须使用“标准”构造函数,该构造函数需要“ flags”参数的值。

public void getListFromDb(){
    Cursor res = myDb.ViewAll();
    startManagingCursor(res);


    //Map cursor from db to viewFields
    String[] fromFieldNames = new String[]{DatabaseHelper.COL_2, DatabaseHelper.COL_3, DatabaseHelper.COL_4, DatabaseHelper.COL_5};
    int[] toViewIDS = new int[]{R.id.viewName, R.id.viewAddress, R.id.viewPostcode, R.id.viewType};

    //Create adaptor to map items from DB to UI
    // *** ADD THE FLAGS PARAMETER ***
    SimpleCursorAdapter myCursorAdaptor = new SimpleCursorAdapter(this, R.id.item_layout, res, fromFieldNames, toViewIDS, FLAG_AUTO_REQUERY);

    // Set adaptor for listView
    ListView myList = (ListView) findViewById(R.id.listViewLocations);
    myList.setAdapter(myCursorAdaptor);

}


我添加了“ FLAG_AUTO_REQUERY”以使更改显而易见,但是我怀疑您可能想使用值“ 0”(无标志),除非您的数据在显示时可以更改。

因此,在重新阅读您的问题(对不起,我的不好;我应该更仔细地阅读:-p)之后,您真正的问题是如何在后台线程上加载数据。有很多方法可以做到,都有优点和缺点。

这个经典的Android问题有两个部分:
1:实际上是将数据加载到后台线程上,并将结果传递给UI线程进行显示。
2:存活的活动破坏/恢复通常是由轮换引起的(但可能是由于无法接听电话而引起的)。

CursorLoader的实现笨拙且笨拙,但实际上确实很好地解决了这两个问题。

AsyncTasks将处理后台执行并将结果传递给ui线程,并且如果您不关心问题2则可以正常工作,但是android中存在一个令人讨厌的小问题,它可能导致一次只运行一个AsyncTask(不是如果您想并行进行很多工作,那就太好了。

还可以使用其他框架来执行此类工作,例如rxJava和otto,但是它们需要付出大量的努力才能初步适应(尽管值得一提)。

如果您需要担心应用程序的旋转和/或中断,我建议CursorLoaders最初可能是最简单的,但仅适用于较简单的应用程序。如果您的应用程序将变得复杂,请花一些时间研究rxJava或Otto。

希望这可以帮助。
附言一个简单的基于asynctask的示例(未经测试,因为我没有您的所有源/资源,但是您明白了。)

public void getListFromDb(){

        //Map cursor from db to viewFields
        String[] fromFieldNames = new String[]{DatabaseHelper.COL_2, DatabaseHelper.COL_3, DatabaseHelper.COL_4, DatabaseHelper.COL_5};
        int[] toViewIDS = new int[]{R.id.viewName, R.id.viewAddress, R.id.viewPostcode, R.id.viewType};


        // Notice I am passing null as the cursor..
        SimpleCursorAdapter myCursorAdaptor = new SimpleCursorAdapter(this, R.id.item_layout, null, fromFieldNames, toViewIDS, 0);
        // Set adaptor for listView
        ListView myList = (ListView) findViewById(R.id.listViewLocations);
        myList.setAdapter(myCursorAdaptor);

        new AsyncTask<SimpleCursorAdapter, Void, Cursor>() {
            private SimpleCursorAdapter mSimpleCursorAdapter;
            @Override
            protected Cursor doInBackground(SimpleCursorAdapter... params) {
                // Save cursorAdapter to use in postExecute
                this.mSimpleCursorAdapter = params[0];
                // Load cursor on background thread
                return myDb.ViewAll();
            }

            @Override
            protected void onPostExecute(Cursor cursor) {
                super.onPostExecute(cursor);
                // and update the cursor (which is already in the listview)
                this.mSimpleCursorAdapter.changeCursor(cursor);
            }
        }.execute(myCursorAdaptor);

    }


主要的“技巧”是,我最初使用空光标创建了simplecursoradapter;这使我可以在屏幕上获取没有数据的列表。然后,我启动一个AsyncTask,将cursoradapter传递给它,并使它将光标加载到后台线程上。然后,我在适配器上调用“ changeCursor”,它应该使用加载的数据更新listview。您还可以使用onPreExecute来显示繁忙的“旋转器”,并在onPostExecute中隐藏繁忙的“旋转器”。.只是为了让用户知道您正在做某事。 onPreExecute和onPostExecute在UI线程上运行,因此可以更新UI,doInBackground在后台线程上运行。

10-07 19:33
查看更多