【问题标题】:Android - Save big JSON to Realm OutOfMemoryExceptionAndroid - 将大 JSON 保存到领域 OutOfMemoryException
【发布时间】:2017-09-11 08:00:58
【问题描述】:

情况:

我的服务器上有一个很大的Json file( >= 50-100Mb ),其中包含我在我的应用上需要的所有客户的信息。

我必须将文件下载到我的应用程序中,并将所有信息保存到我的Realm 数据库中。 (该文件中有近 200k 个对象)。

Customer.class

这是保存在这个数组中的对象:

public class Customer  extends RealmObject {
    public Customer(){}

    @PrimaryKey
    private String ID;
    private String FULL_NAME;
    private String PHONE_NO;
    private String CODICE_FISCALE;
    private Date MODIFIED_ON;

    //getters and setters

我的下载和保存代码:

这是AsyncTask,我删除了所有无用的代码以便于查看

    @Override
    protected Void doInBackground(String... params) {
        Realm realm = null;
        newSha = null;
        try {
            realm = Realm.getDefaultInstance();

            String url = "myurl";
            OkHttpClient client = new OkHttpClient.Builder()
                    .connectTimeout(10, TimeUnit.SECONDS)
                    .writeTimeout(120, TimeUnit.SECONDS)
                    .readTimeout(120, TimeUnit.SECONDS)
                    .build();

            Request request = new Request.Builder().url(url)
                    .addHeader("Content-Type", "application/json")
                    .build();

            Response response = client.newCall(request).execute();
            ResponseBody responseBody = response.body();

            try {
                String myHeader = response.header("Content-Disposition");
                if (myHeader != null) {
                    int position = myHeader.indexOf("filename=");
                    position += "filename=".length();
                    newSha = myHeader.substring(position);
                }
            } catch (Exception ex) {
                newSha = null;
            }

            if (responseBody == null) {
                return null;
            }
            InputStream is = responseBody.byteStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(is));
            final StringBuilder sb = new StringBuilder();

            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }

            response.close();
            responseBody.close();
            is.close();
            reader.close();

            //switch because i have 20-30 cases, this is the big file which gives problems
            switch (fileName) {
                case "Customers": {
                    realm.executeTransaction(new Realm.Transaction() {
                        @Override
                        public void execute(Realm realm) {
                            try {
                                Log.wtf("SYNC", "Customer - start delete");
                                realm.delete(Customer.class);
                                Log.wtf("SYNC", "Customer - end delete, start create");  //this line is reached
                                realm.createAllFromJson(Customer.class, sb.toString());  
                                Log.wtf("SYNC", "Customer - end create");                //this line is never reached
                                setTitle(String.format("Completato! [%s]", title));

                                publishProgress(100, 1);
                                addSyncCompleted(false, null, null);
                                genericDbClass.setSHA(realm, new Customer(), newSha);
                            } catch (Exception error) {
                                newSha = null;                                            //this error is never thrown
                            }
                        }
                    });
                }
                break;

问题:

realm.createAllFromJson 抛出一个 OutOfMemoryException(不是真的抛出,应用程序刚刚关闭,没有触发捕获并且没有任何错误。我在日志中看到的只是一些这样的异常记录为警告

W/art: Throwing OutOfMemoryError "Failed to allocate a 170348044 byte allocation with 16777216 free bytes and 162MB until OOM"

问题在于如何将这个大的 Json 文件保存到 Realm 中。我之前也尝试过用 Gson 解析这个字符串,但没有成功。该文件可能会随着时间的推移而增加大小,那么我该如何加快速度呢?

任何帮助将不胜感激,我已经坚持了一周。

【问题讨论】:

  • 你为什么不破坏数据并在你的应用程序中接收?
  • @phpdroid 抱歉,我没听懂,这是什么意思? (我对流和领域还很陌生)
  • @PierGiorgioMisley 不是一次下载所有客户或所有记录,而是进行分页,下载前 20 个,下一个 20 和下一个 20 等等....
  • 嘿,我这里没有用大词,只是尝试像分页这样的东西来接收我的意思。
  • 哦,对不起,我没有意识到你是认真的!谢谢。。我会试试的!去谷歌搜索一些方法

标签: android json out-of-memory realm


【解决方案1】:

Realm 有一个 createAllFromJson() 的流式变体,它直接接受 InputStreamhttps://realm.io/docs/java/3.7.1/api/io/realm/Realm.html#createAllFromJson-java.lang.Class-java.io.InputStream-

这也应该可以防止内存不足。

【讨论】:

  • 我还是不明白我怎么没看到这个。感谢您在领域的出色工作!
猜你喜欢
  • 2021-09-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-02
  • 1970-01-01
相关资源
最近更新 更多