【问题标题】:Android performing a large sqllite write in async task freezes the UIAndroid 在异步任务中执行大型 sqllite 写入会冻结 UI
【发布时间】:2017-01-12 07:07:08
【问题描述】:

所以我正在编写一个应用程序,它在首次运行时需要从网络中提取一些数据并将其写入数据库表。问题是它使 UI 线程崩溃。它在异步任务中运行,但仍会导致 UI 出现问题。我并不真正关心进展或知道何时完成。只是希望它在用户不知情的情况下做自己的事情。

它不是大量的数据。 JSON 响应小于 600kb,数据库中大约有 9,000 行。只需要大约 30-45 秒,但我宁愿让应用程序的其余部分在那段时间内可用。

这是我在异步任务中构建数据库的一些设置。

public void updateDBBackground() {
    new UpdateDbTask().execute("", "", "");
}


private class UpdateDbTask extends AsyncTask<String, String, String> {
    protected String doInBackground(String... urls) {
        long totalSize = 0;
        open();
        String url = "someurl";

        JsonObjectRequest jsObjRequest = new JsonObjectRequest
                (Request.Method.GET, url, null, new Response.Listener<JSONObject>() {

                    @Override
                    public void onResponse(JSONObject response) {
                        try {
                            JSONArray queuearray = response.getJSONArray("items");
                            for (int i = 0; i < queuearray.length(); i++) {
                                if (!queuearray.getJSONObject(i).getString("artist").isEmpty()) {
                                    insert(queuearray.getJSONObject(i).getLong("id"), queuearray.getJSONObject(i).getString("item1"), queuearray.getJSONObject(i).getString("item2"));
                                }
                            }

                        } catch (Exception e) {

                        }
                    }
                }, new Response.ErrorListener() {

                    @Override
                    public void onErrorResponse(VolleyError error) {


                    }
                });

        VolleySig.getInstance(context).addToRequestQueue(jsObjRequest);

        return "";
    }

    protected void onProgressUpdate(String... progress) {
    }

    protected void onPostExecute(String result) {
    }
}

我从主要活动中调用所有这些。

   DBManager db = new DBManager(this);
    if (!db.checkDb()) {
        db.updateDBBackground();
    }

这是崩溃报告数据。

09-04 17:20:29.065 18263-18270/com.SOMEAPP I/art: Thread[3,tid=18270,WaitingInMainSignalCatcherLoop,Thread*=0x7a74799000,peer=0x12ccb160,"Signal Catcher"]: reacting to signal 3
09-04 17:20:29.155 18263-18270/com.SOMEAPP I/art: Wrote stack traces to '/data/anr/traces.txt'

这是traces.txt的内容

http://pastebin.com/traces

【问题讨论】:

  • 能否也粘贴故障转储?
  • 这是使用 Service 的一个很好的用例,您的任务没有理由应该在 Activity 中运行。
  • 添加了相关的崩溃数据。我考虑过使用服务。一次似乎有点多。所以它从一个活动开始,因为这只是应用程序做的第一件事。打开它,进入家庭活动。
  • 尝试使用服务并在其中处理我自己的线程。仍然锁定用户界面。我尝试了一个意图服务并让它执行请求并将项目添加到数据库中。甚至锁定了 UI。
  • 您正在使用 MainActivity 来初始化 DBManager。看起来这打破了活动生命周期。您的用户是否被转发到另一个活动?但是,如果您将内容移动到服务中,这是没有意义的。 open 方法有什么用?

标签: android multithreading sqlite asynchronous android-asynctask


【解决方案1】:

原来它是在后台线程中执行项目,但产生的项目足够多,导致 UI 挂起。

出于一些原因,我将数据库从 Sqllite 切换到了 Realm,现在我正在加载项目。有时可能会有一到两秒的 UI 滞后,但没有什么太大的影响。

    private void UpdateDB() {
    String url = "http://example.com&return=JSON";

    JsonObjectRequest jsObjRequest = new JsonObjectRequest
            (Request.Method.GET, url, null, new Response.Listener<JSONObject>() {

                @Override
                public void onResponse(JSONObject response) {
                    try {
                        final JSONArray queuearray = response.getJSONArray("items");

                        realmConfig = new RealmConfiguration.Builder(getApplicationContext()).build();
                        // Open the Realm for the UI thread.
                        realm = Realm.getInstance(realmConfig);


                        realm.executeTransaction(new Realm.Transaction() {
                            @Override
                            public void execute(Realm realm) {
                                // Add a person

                                for (int i = 0; i < queuearray.length(); i++) {

                                    try {
                                        if (!queuearray.getJSONObject(i).getString("value").isEmpty()) {
                                            Media media = realm.createObject(Media.class);
                                            media.setValue(queuearray.getJSONObject(i).getString("value"));
                                            media.setTitle(queuearray.getJSONObject(i).getString("title"));
                                            media.setItemid(queuearray.getJSONObject(i).getLong("itemid"));
                                        }
                                    } catch (Exception e) {

                                    }
                                }

                            }
                        });


                    } catch (Exception e) {


                    }
                }
            }, new Response.ErrorListener() {

                @Override
                public void onErrorResponse(VolleyError error) {

                }
            });

    VolleySig.getInstance(this).addToRequestQueue(jsObjRequest);

    realm.close();
}

【讨论】:

    猜你喜欢
    • 2015-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多