java - AsyncTask 完成,但 Activity UI 未更新超过 20 秒

标签 java android

我有一个用于查询数据库的 AsyncTask,但 UI 更新可能需要 20 多秒。起初我以为是数据库查询速度慢,但在输入一些调试语句后,事实证明一切实际上都很快完成了。 onPostExecute 中的最后一条指令完成,然后 20 多秒后 UI 终于更新。这发生在运行 Android 9 Pie 的手机上,在早期版本上它要快得多。为什么会这样?可能发生了什么? 编辑:在运行 Android 7 的手机上,大约需要 2 秒。

void callBackgroundQuery(String query){
    backgroundQuery BQ = new backgroundQuery(this);
    BQ.execute(query);
}

private class backgroundQuery extends AsyncTask<String, Void, String>{
    private ReadingActivity mReadingActivity;

    public backgroundQuery(ReadingActivity ra){
        mReadingActivity = ra;
    }

    @Override
    protected String doInBackground(String... query) {
        System.out.println("Getting DB Instance");
        SQLiteDatabase db = mDbHelper.getInstance(getApplicationContext()).getReadableDatabase();
        System.out.println("Querying DB");
        Cursor c = db.rawQuery(query[0],null);
        StringBuilder builder = new StringBuilder();
        String chap, verse, text;
        int bookNum;
        System.out.println("Moving to first and parsing lines");
        c.moveToFirst();
        while (!c.isAfterLast()) {
            bookNum = c.getInt(0);
            chap = c.getString(1);
            verse = c.getString(2);
            text = c.getString(3);
            String completeVerse = getAbbreviation(bookNum) + " " + chap + ":" + verse + " " + text;
            builder.append(completeVerse).append("\n");
            c.moveToNext();
        }
        System.out.println("Finished parsing, starting builder.toString()");
        String completeText = builder.toString();
        System.out.println("Finished building string, returning and setting text");
        return completeText;
    }

    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        System.out.println("Setting text");
        mTextView.setText(result);
        System.out.println("Setting scroll");
        mReadingActivity.setScroll();
        // This outputs, and 20+ seconds later the TextView displays the text
        System.out.println("Finished setting scroll");
    }
}

最佳答案

为了解决 Android Pie 缓慢的 setText 问题,我按照评论中的建议使用了 PrecomputedText。我根据 SDK 版本制作了单独的 AsyncTask 类供使用。我不知道是否有更好的方法来处理该部分,但我的问题的真正解决方案是在 Android 9 中使用 PrecomputedText。

void callBackgroundQuery(String query){
    if (android.os.Build.VERSION.SDK_INT >= 28){
        backgroundQueryAPI28 BQ = new backgroundQueryAPI28(this);
        BQ.execute(query);
    } else {
        backgroundQuery BQ = new backgroundQuery(this);
        BQ.execute(query);
    }
}

private class backgroundQueryAPI28 extends AsyncTask<String, Void, PrecomputedText>{
    private ReadingActivity mReadingActivity;

    final PrecomputedText.Params params = mTextView.getTextMetricsParams();
    final Reference textViewRef = new WeakReference<>(mTextView);

    public backgroundQueryAPI28(ReadingActivity ra){
        mReadingActivity = ra;
    }

    @Override
    protected PrecomputedText doInBackground(String... query) {
        SQLiteDatabase db = mDbHelper.getInstance(getApplicationContext()).getReadableDatabase();
        Cursor c = db.rawQuery(query[0],null);
        StringBuilder builder = new StringBuilder();
        String chap, verse, text;
        int bookNum;
        c.moveToFirst();
        while (!c.isAfterLast()) {
            bookNum = c.getInt(0);
            chap = c.getString(1);
            verse = c.getString(2);
            text = c.getString(3);
            String completeVerse = getAbbreviation(bookNum) + " " + chap + ":" + verse + " " + text;
            builder.append(completeVerse).append("\n");
            c.moveToNext();
        }

        String allText = builder.toString();
        final PrecomputedText precomputedText = PrecomputedText.create(allText, params);
        return precomputedText;
    }

    @Override
    protected void onPostExecute(PrecomputedText result) {
        super.onPostExecute(result);
        mTextView.setText(result);
        mReadingActivity.setScroll();
    }
}

private class backgroundQuery extends AsyncTask<String, Void, String>{
    private ReadingActivity mReadingActivity;

    public backgroundQuery(ReadingActivity ra){
        mReadingActivity = ra;
    }

    @Override
    protected String doInBackground(String... query) {
        SQLiteDatabase db = mDbHelper.getInstance(getApplicationContext()).getReadableDatabase();
        Cursor c = db.rawQuery(query[0],null);
        StringBuilder builder = new StringBuilder();
        String chap, verse, text;
        int bookNum;
        c.moveToFirst();
        while (!c.isAfterLast()) {
            bookNum = c.getInt(0);
            chap = c.getString(1);
            verse = c.getString(2);
            text = c.getString(3);
            String completeVerse = getAbbreviation(bookNum) + " " + chap + ":" + verse + " " + text;
            builder.append(completeVerse).append("\n");
            c.moveToNext();
        }

        String allText = builder.toString();
        return allText;
    }

    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        mTextView.setText(result);
        mReadingActivity.setScroll();
    }
}

关于java - AsyncTask 完成,但 Activity UI 未更新超过 20 秒,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53675515/

相关文章:

java - 使用 CriteriaBuilder 进行动态查询 : one-to-many

java - 将对象分配给字符串

java - 如何检查 Linux 中的进程是否正在运行?

android - NoActionBar 相当于 Sherlock ActionBar

android - 在 AsyncTask 上调用 execute() 不会调用 doInBackground()

android - Unresolved reference : lparams for verticalLayout in Anko 0. 10.6

android - AsyncTask #3 错误解析 JSON 对象。字符串无法转换为 JSONObject

c# - 将 Xamarin.forms 应用程序上的目标框架从 Android 8.1 更改为 Android 9(对于 Xamarin.Essentials)

java - 在主类中使用方法设置对象值?

java - System.out.println 在打印计算结果为 boolean 值的内容时没有执行我所期望的操作