如何最有效地从Android SQLite数据库加载对象并按顺序将它们上载到远程实例

时间:2014-07-31 17:11:54

标签: android sql sqlite android-asynctask android-sqlite

基本情况:

在我的Android应用中,我在多个SQLite表中收集了大量不同的数据。后来,这些表被上传到CouchDB服务器 - 每个表作为一个新的数据库,表的每一行作为单独的文件。我知道简单地将关系数据库的设计一对一地转移到基于文档的设计是不好的方式,但是,这一点现在不应该打扰我们:)

问题空间:

我的问题是有些表包含超过5000行。在我当前的代码中,我只是迭代所有表和每个表的所有行。然后,对于每一行,我将数据提取到相应的对象A并将其捆绑到所需的CouchDB文档结构,即包含字段"_rev":String"_id":String"NAME_OF_OBJECT_A":JSONObject的文档。

接下来,AsyncTask开始将这样一个可上传的对象(在我的CouchDBDocument类型的代码中)捆绑到JSON,然后将其上传到相应的现有CouchDB数据库中。

private void uploadNewSQLiteEntries() {
    // Iterate over all tables that have to be uploaded 
    for (AbstractDataSource dataSource : DataSourceHandler.getInstance(mContext).getAllUploadableDataSources()) {           

        // For each table, sequentially extract each row and transfrom it into the respective object
        for (AbstractLoggedObject object : dataSource.getEntriesCreatedSince(lastUploadTime())) {
            try {
                // Bundle it up into the upload format and start async upload thread
                String jsonBody = (new Gson()).toJson(object.encrypt(mContext));
                CouchDBDocument uploadDocument = new CouchDBDocument(object.getId(), uploadDatabaseName(dataSource.getTableName()), mBasisUrl, jsonBody);
                (new AsyncUploadTask()).execute(uploadDocument);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (Throwable e) {
                e.printStackTrace();
            }
        }
    }
}


private class AsyncUploadTask extends AsyncTask<CouchDBDocument, String, Boolean> {

    @Override
    protected Boolean doInBackground(CouchDBDocument... params) {
        CouchDBDocument uploadDocument = params[0];
        String jsonUploadDocument = (new Gson()).toJson(uploadDocument);

        // Executes an HTTP PUT at the specified url and with the specified json document
        return putJSON(jsonUploadDocument, uploadDocument.getBasisUrl()+"/"+uploadDocument.getDatabaseName()+"/"+uploadDocument.getId());
    }   

    @Override
    protected void onPostExecute(Boolean success) {
        if (success) {
            Log.e("CouchDBUploadHandler", "Upload finished with success=true");
        } else {
            Log.e("CouchDBUploadHandler", "Upload failed");
        }
    }
}

我的问题

由于大量数据和一次执行多个AsyncTasks,我担心在某些情况下我的应用可能最终会耗尽内存。那么为了得到我的实际问题,你会如何解决这个问题?

  • 是否有一种优雅而直接的方法,一次只启动一个异步任务?

  • 如何处理对象。现在,我要上传的对象一次性存储到一个ArrayList中,然后逐步转换和更新。如果一个表由5000行组成,这不仅需要时间,而且还会占用大量内存。 有没有更简单的解决方案,甚至一次只能将SQLite表中的一个对象加载到内存中?

1 个答案:

答案 0 :(得分:0)

我的解决方案是通过队列使用多种线程样式:

1)将要上传的所有对象放入阻塞队列(java安全线程)。

2)你有两个东西:一个从db读取并将你的对象放入队列,另一个从队列读取 将您的对象发送到线程。这是一个具有可配置线程池大小的网络调度程序。

如果您填充队列的速度比另一个线程从队列中读取队列并将其存储在磁盘上并使网络调度程序使用磁盘存储器更快,则还可以放置另一个级别。

通过这种方式,您可以完全控制所有员工和线程,并且可以轻松配置

祝你好运