3

我习惯在 Android 中使用 Loader 和 CursorAdapter。查看适用于 Android 的 Couchbase-Lite,我看不到一种以我认为是内存友好的方式填充 ListView 的方法。

在此处查看示例应用程序中的代码: https ://github.com/couchbaselabs/GrocerySync-Android/blob/master/GrocerySync-Android/src/main/java/com/couchbase/grocerysync/MainActivity.java

protected void startCBLite() throws Exception {
    manager = new Manager(getApplicationContext().getFilesDir(), Manager.DEFAULT_OPTIONS);
    //install a view definition needed by the application
    database = manager.getDatabase(DATABASE_NAME);
    com.couchbase.lite.View viewItemsByDate = database.getView(String.format("%s/%s", designDocName, byDateViewName));
    viewItemsByDate.setMap(new Mapper() {
        @Override
        public void map(Map<String, Object> document, Emitter emitter) {
            Object createdAt = document.get("created_at");
            if (createdAt != null) {
                emitter.emit(createdAt.toString(), null);
            }
        }
    }, "1.0");


    startLiveQuery(viewItemsByDate);

    startSync();

}

private void startSync() {

    URL syncUrl;
    try {
        syncUrl = new URL(SYNC_URL);
    } catch (MalformedURLException e) {
        throw new RuntimeException(e);
    }

    Replication pullReplication = database.createPullReplication(syncUrl);
    pullReplication.setContinuous(true);

    Replication pushReplication = database.createPushReplication(syncUrl);
    pushReplication.setContinuous(true);

    pullReplication.start();
    pushReplication.start();

    pullReplication.addChangeListener(this);
    pushReplication.addChangeListener(this);

}

private void startLiveQuery(com.couchbase.lite.View view) throws Exception {

    final ProgressDialog progressDialog = showLoadingSpinner();

    if (liveQuery == null) {

        liveQuery = view.createQuery().toLiveQuery();

        liveQuery.addChangeListener(new LiveQuery.ChangeListener() {
            @Override
            public void changed(LiveQuery.ChangeEvent event) {
                displayRows(event.getRows());
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        progressDialog.dismiss();
                    }
                });
            }
        });

        liveQuery.start();

    }

}

private void displayRows(QueryEnumerator queryEnumerator) {

    final List<QueryRow> rows = getRowsFromQueryEnumerator(queryEnumerator);

    runOnUiThread(new Runnable() {
        @Override
        public void run() {

            itemListViewAdapter = new GrocerySyncListAdapter(
                    getApplicationContext(),
                    R.layout.grocery_list_item,
                    R.id.label,
                    rows
            );
            itemListView.setAdapter(itemListViewAdapter);
            itemListView.setOnItemClickListener(MainActivity.this);
            itemListView.setOnItemLongClickListener(MainActivity.this);

        }
    });
}


private List<QueryRow> getRowsFromQueryEnumerator(QueryEnumerator queryEnumerator) {
    List<QueryRow> rows = new ArrayList<QueryRow>();
    for (Iterator<QueryRow> it = queryEnumerator; it.hasNext();) {
        QueryRow row = it.next();
        rows.add(row);
    }
    return rows;
}

在这里: https ://github.com/couchbaselabs/GrocerySync-Android/blob/master/GrocerySync-Android/src/main/java/com/couchbase/grocerysync/GrocerySyncListAdapter.java

@Override
public View getView(int position, View itemView, ViewGroup parent) {
   ...
   QueryRow row = list.get(position);
   Document document = row.getDocument();
   ...
}

查询返回一个枚举器,然后循环创建 ArrayList,然后将其传递给查询适配器。这一切都在 UI 线程上完成。

这对于一个简单的杂货店应用程序演示来说可能很好,但如果我的数据库中有 20,000 个文档,并且有 18,000 个文档响应我的查询,该怎么办?

4

1 回答 1

0

查看 TodoLite Android 示例项目。在那检查TaskAdapter。通过直接在 BaseAdapter 中使用 queryEnumertor 来处理这种情况下面是指向包含 TaskAdapter 类的 MainActivity 的链接

https://github.com/couchbaselabs/ToDoLite-Android/blob/master/ToDoLite/src/main/java/com/couchbase/todolite/MainActivity.java

于 2014-10-31T09:30:19.380 回答