Android appUI更新慢

Android appUI updating slow

在我的应用程序中,当单击按钮时,首先更新数据库,然后将数据发送到服务器。在发送数据之前,该数据已加密。对数据库的更新是在一个异步任务中完成的,加密和发送数据是通过另一个异步任务完成的,如下所示

1) 更新数据库

 private class UpdateThread extends AsyncTask<Void, Void, Void> {
    private MessageThread messageThread;

    private UpdateThread(MessageThread thread) {
        this.messageThread = thread;
    }

    @Override
    protected Void doInBackground(Void... params) {
        action.update(messageThread);

        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);

        PollReply pollReply = new PollReply(messageThread);
        pollReply.execute();
    }
}

2) 加密数据并发送到服务器

private class PollReply extends AsyncTask<Void, Void, Void> {
    private MessageThread messageThread;

    private PollReply(MessageThread thread) {
        this.messageThread = thread;
    }

    @Override
    protected Void doInBackground(Void... params) {

        messageThread.setHashcode(HashUtility.encryptString(messageThread.getRandomcode() + messageThread.getUserId()));
        messageThread.setStrippedHashCode(StringUtility.reduceToBytes(messageThread.getHashcode(), 16));
        try {
            messageThread.setAnswerEnc(EncryptionUtility.encrypt(messageThread.getAnswer(), messageThread.getStrippedHashCode()));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        }


        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);

        PollReplyAsyncTask asyncTask = new PollReplyAsyncTask(activity, false, messageThread, messageThread.getUserId());
        asyncTask.execute();
    }
}

这些异步任务的调用方式如下

UpdateThread updateThread = new UpdateThread(message);
updateThread.execute();

PollReply pollReply = new PollReply(message);
pollReply.execute();

当我评论第二个异步任务时,数据库会立即更新,UI 也会立即更新。 但是当我使用第二个异步任务时,数据库会更新,但 ui 在执行第二个异步任务后会更新。我认为 UI 线程在某处被阻塞。这个问题有什么解决办法吗?

if (message.getOptionsCount() > 0) {

                    if (message.getOptionsCount() > 1) {
                        pollChoice1.setText(message.getOption1());
                        pollChoice2.setText(message.getOption2());

                        backgroundWidth = 0;
                        if (message.getOptionsCount() == 2) {
                            pollChoice1.setVisibility(View.VISIBLE);
                            pollChoice2.setVisibility(View.VISIBLE);
                            pollChoice3.setVisibility(View.GONE);
                            pollChoice4.setVisibility(View.GONE);
                            pollChoice5.setVisibility(View.GONE);

                            if ((message.getVisibility().equals("public") && message.getAnswered()) || (message.getType() == MessageThread.OUT_MESSAGE)) {
                                pollChoice3Background.setVisibility(View.GONE);
                                pollChoice4Background.setVisibility(View.GONE);
                                pollChoice5Background.setVisibility(View.GONE);

                                if (responseCount > 0) {
                                    pollChoice1Background.setVisibility(View.VISIBLE);
                                    pollChoice2Background.setVisibility(View.VISIBLE);

                                    float widthFloat = (float) (option1Count * 100.0 / responseCount);
                                    backgroundWidth = (int) widthFloat;
                                    int total_width = pollChoice1.getMeasuredWidth();
                                    pollChoice1Background.setText("" + backgroundWidth + "%");
                                    backgroundWidth = (total_width * backgroundWidth / 100);
                                    pollChoice1Background.getLayoutParams().width = backgroundWidth;

                                    widthFloat = (float) (option2Count * 100.0 / responseCount);
                                    backgroundWidth = (int) widthFloat;
                                    total_width = pollChoice1.getMeasuredWidth();
                                    pollChoice2Background.setText("" + backgroundWidth + "%");
                                    backgroundWidth = (total_width * backgroundWidth / 100);
                                    pollChoice2Background.getLayoutParams().width = backgroundWidth;
                                } else {
                                    pollChoice1Background.setVisibility(View.INVISIBLE);
                                    pollChoice2Background.setVisibility(View.INVISIBLE);
                                }
                            } else {
                                pollChoice1Background.setVisibility(View.INVISIBLE);
                                pollChoice2Background.setVisibility(View.INVISIBLE);
                            }

                            line1choice.setVisibility(View.VISIBLE);
                            line2choice.setVisibility(View.VISIBLE);
                            line3choice.setVisibility(View.VISIBLE);

                            choice1Layout.setVisibility(View.VISIBLE);
                            choice2Layout.setVisibility(View.VISIBLE);
                            choice3Layout.setVisibility(View.GONE);
                            choice4Layout.setVisibility(View.GONE);
                            choice5Layout.setVisibility(View.GONE);
                            choice6Layout.setVisibility(View.GONE);

                        } else if (message.getOptionsCount() == 3) {

                            dps = 150;
                            pixels = (int) (dps * scale + 0.5f);
                            feed.getLayoutParams().height = pixels;

                            pollChoice1.setText(message.getOption1());
                            pollChoice2.setText(message.getOption2());
                            pollChoice3.setText(message.getOption3());

                            pollChoice1.setVisibility(View.VISIBLE);
                            pollChoice2.setVisibility(View.VISIBLE);
                            pollChoice3.setVisibility(View.VISIBLE);
                            pollChoice4.setVisibility(View.GONE);
                            pollChoice5.setVisibility(View.GONE);

                            if ((message.getVisibility().equals("public") && message.getAnswered()) || (message.getType() == MessageThread.OUT_MESSAGE)) {
                                pollChoice4Background.setVisibility(View.GONE);
                                pollChoice5Background.setVisibility(View.GONE);

                                if (responseCount > 0) {
                                    pollChoice1Background.setVisibility(View.VISIBLE);
                                    pollChoice2Background.setVisibility(View.VISIBLE);
                                    pollChoice3Background.setVisibility(View.VISIBLE);


                                    float width_float = (float) (option1Count * 100.0 / responseCount);
                                    backgroundWidth = (int) width_float;
                                    int total_width = pollChoice1.getMeasuredWidth();
                                    pollChoice1Background.setText("" + backgroundWidth + "%");
                                    backgroundWidth = (total_width * backgroundWidth / 100);
                                    pollChoice1Background.getLayoutParams().width = backgroundWidth;

                                    width_float = (float) (option2Count * 100.0 / responseCount);
                                    backgroundWidth = (int) width_float;
                                    total_width = pollChoice2.getMeasuredWidth();
                                    pollChoice2Background.setText("" + backgroundWidth + "%");
                                    backgroundWidth = (total_width * backgroundWidth / 100);
                                    pollChoice2Background.getLayoutParams().width = backgroundWidth;

                                    width_float = (float) (option3Count * 100.0 / responseCount);
                                    backgroundWidth = (int) width_float;
                                    total_width = pollChoice3.getMeasuredWidth();
                                    pollChoice3Background.setText("" + backgroundWidth + "%");
                                    backgroundWidth = (total_width * backgroundWidth / 100);
                                    pollChoice3Background.getLayoutParams().width = backgroundWidth;
                                } else {
                                    pollChoice1Background.setVisibility(View.INVISIBLE);
                                    pollChoice2Background.setVisibility(View.INVISIBLE);
                                    pollChoice3Background.setVisibility(View.INVISIBLE);
                                }
                            } else {
                                pollChoice1Background.setVisibility(View.INVISIBLE);
                                pollChoice2Background.setVisibility(View.INVISIBLE);
                                pollChoice3Background.setVisibility(View.INVISIBLE);
                            }

                            line1choice.setVisibility(View.VISIBLE);
                            line2choice.setVisibility(View.VISIBLE);
                            line3choice.setVisibility(View.VISIBLE);
                            line4choice.setVisibility(View.VISIBLE);

                            choice1Layout.setVisibility(View.VISIBLE);
                            choice2Layout.setVisibility(View.VISIBLE);
                            choice3Layout.setVisibility(View.VISIBLE);
                            choice4Layout.setVisibility(View.GONE);
                            choice5Layout.setVisibility(View.GONE);
                            choice6Layout.setVisibility(View.GONE);
                        } else if (message.getOptionsCount() == 4) {

                            dps = 100;
                            pixels = (int) (dps * scale + 0.5f);
                            feed.getLayoutParams().height = pixels;

                            pollChoice1.setText(message.getOption1());
                            pollChoice2.setText(message.getOption2());
                            pollChoice3.setText(message.getOption3());
                            pollChoice4.setText(message.getOption4());

                            pollChoice1.setVisibility(View.VISIBLE);
                            pollChoice2.setVisibility(View.VISIBLE);
                            pollChoice3.setVisibility(View.VISIBLE);
                            pollChoice4.setVisibility(View.VISIBLE);
                            pollChoice5.setVisibility(View.GONE);

                            if ((message.getVisibility().equals("public") && message.getAnswered()) || (message.getType() == MessageThread.OUT_MESSAGE)) {
                                pollChoice5Background.setVisibility(View.GONE);

                                if (responseCount > 0) {
                                    pollChoice1Background.setVisibility(View.VISIBLE);
                                    pollChoice2Background.setVisibility(View.VISIBLE);
                                    pollChoice3Background.setVisibility(View.VISIBLE);
                                    pollChoice4Background.setVisibility(View.VISIBLE);

                                    float width_float = (float) (option1Count * 100.0 / responseCount);
                                    backgroundWidth = (int) width_float;
                                    int total_width = pollChoice1.getMeasuredWidth();
                                    pollChoice1Background.setText("" + backgroundWidth + "%");
                                    backgroundWidth = (total_width * backgroundWidth / 100);
                                    pollChoice1Background.getLayoutParams().width = backgroundWidth;

                                    width_float = (float) (option2Count * 100.0 / responseCount);
                                    backgroundWidth = (int) width_float;
                                    total_width = pollChoice2.getMeasuredWidth();
                                    pollChoice2Background.setText("" + backgroundWidth + "%");
                                    backgroundWidth = (total_width * backgroundWidth / 100);
                                    pollChoice2Background.getLayoutParams().width = backgroundWidth;

                                    width_float = (float) (option3Count * 100.0 / responseCount);
                                    backgroundWidth = (int) width_float;
                                    total_width = pollChoice3.getMeasuredWidth();
                                    pollChoice3Background.setText("" + backgroundWidth + "%");
                                    backgroundWidth = (total_width * backgroundWidth / 100);
                                    pollChoice3Background.getLayoutParams().width = backgroundWidth;

                                    width_float = (float) (option4Count * 100.0 / responseCount);
                                    backgroundWidth = (int) width_float;
                                    total_width = pollChoice4.getMeasuredWidth();
                                    pollChoice4Background.setText("" + backgroundWidth + "%");
                                    backgroundWidth = (total_width * backgroundWidth / 100);
                                    pollChoice4Background.getLayoutParams().width = backgroundWidth;
                                } else {
                                    pollChoice1Background.setVisibility(View.INVISIBLE);
                                    pollChoice2Background.setVisibility(View.INVISIBLE);
                                    pollChoice3Background.setVisibility(View.INVISIBLE);
                                    pollChoice4Background.setVisibility(View.INVISIBLE);
                                }
                            } else {
                                pollChoice1Background.setVisibility(View.INVISIBLE);
                                pollChoice2Background.setVisibility(View.INVISIBLE);
                                pollChoice3Background.setVisibility(View.INVISIBLE);
                                pollChoice4Background.setVisibility(View.INVISIBLE);
                            }

                            line1choice.setVisibility(View.VISIBLE);
                            line2choice.setVisibility(View.VISIBLE);
                            line3choice.setVisibility(View.VISIBLE);
                            line4choice.setVisibility(View.VISIBLE);
                            line5choice.setVisibility(View.VISIBLE);

                            choice1Layout.setVisibility(View.VISIBLE);
                            choice2Layout.setVisibility(View.VISIBLE);
                            choice3Layout.setVisibility(View.VISIBLE);
                            choice4Layout.setVisibility(View.VISIBLE);
                            choice5Layout.setVisibility(View.GONE);
                            choice6Layout.setVisibility(View.GONE);
                        } else if (message.getOptionsCount() == 5) {

                            dps = 100;
                            pixels = (int) (dps * scale + 0.5f);
                            feed.getLayoutParams().height = pixels;

                            pollChoice1.setText(message.getOption1());
                            pollChoice2.setText(message.getOption2());
                            pollChoice3.setText(message.getOption3());
                            pollChoice4.setText(message.getOption4());
                            pollChoice5.setText(message.getOption5());

                            pollChoice1.setVisibility(View.VISIBLE);
                            pollChoice2.setVisibility(View.VISIBLE);
                            pollChoice3.setVisibility(View.VISIBLE);
                            pollChoice4.setVisibility(View.VISIBLE);
                            pollChoice5.setVisibility(View.VISIBLE);

                            if ((message.getVisibility().equals("public") && message.getAnswered()) || (message.getType() == MessageThread.OUT_MESSAGE)) {
                                if (responseCount > 0) {
                                    pollChoice1Background.setVisibility(View.VISIBLE);
                                    pollChoice2Background.setVisibility(View.VISIBLE);
                                    pollChoice3Background.setVisibility(View.VISIBLE);
                                    pollChoice4Background.setVisibility(View.VISIBLE);
                                    pollChoice5Background.setVisibility(View.VISIBLE);

                                    float width_float = (float) (option1Count * 100.0 / responseCount);
                                    backgroundWidth = (int) width_float;
                                    int total_width = pollChoice1.getMeasuredWidth();
                                    pollChoice1Background.setText("" + backgroundWidth + "%");
                                    backgroundWidth = (total_width * backgroundWidth / 100);
                                    pollChoice1Background.getLayoutParams().width = backgroundWidth;

                                    width_float = (float) (option2Count * 100.0 / responseCount);
                                    backgroundWidth = (int) width_float;
                                    total_width = pollChoice2.getMeasuredWidth();
                                    pollChoice2Background.setText("" + backgroundWidth + "%");
                                    backgroundWidth = (total_width * backgroundWidth / 100);
                                    pollChoice2Background.getLayoutParams().width = backgroundWidth;

                                    width_float = (float) (option3Count * 100.0 / responseCount);
                                    backgroundWidth = (int) width_float;
                                    total_width = pollChoice3.getMeasuredWidth();
                                    pollChoice3Background.setText("" + backgroundWidth + "%");
                                    backgroundWidth = (total_width * backgroundWidth / 100);
                                    pollChoice3Background.getLayoutParams().width = backgroundWidth;

                                    width_float = (float) (option4Count * 100.0 / responseCount);
                                    backgroundWidth = (int) width_float;
                                    total_width = pollChoice4.getMeasuredWidth();
                                    pollChoice4Background.setText("" + backgroundWidth + "%");
                                    backgroundWidth = (total_width * backgroundWidth / 100);
                                    pollChoice4Background.getLayoutParams().width = backgroundWidth;

                                    width_float = (float) (option5Count * 100.0 / responseCount);
                                    backgroundWidth = (int) width_float;
                                    total_width = pollChoice5.getMeasuredWidth();
                                    pollChoice5Background.setText("" + backgroundWidth + "%");
                                    backgroundWidth = (total_width * backgroundWidth / 100);
                                    pollChoice5Background.getLayoutParams().width = backgroundWidth;

                                } else {
                                    pollChoice1Background.setVisibility(View.INVISIBLE);
                                    pollChoice2Background.setVisibility(View.INVISIBLE);
                                    pollChoice3Background.setVisibility(View.INVISIBLE);
                                    pollChoice4Background.setVisibility(View.INVISIBLE);
                                    pollChoice5Background.setVisibility(View.INVISIBLE);
                                }
                            } else {
                                pollChoice1Background.setVisibility(View.INVISIBLE);
                                pollChoice2Background.setVisibility(View.INVISIBLE);
                                pollChoice3Background.setVisibility(View.INVISIBLE);
                                pollChoice4Background.setVisibility(View.INVISIBLE);
                                pollChoice5Background.setVisibility(View.INVISIBLE);
                            }

                            line1choice.setVisibility(View.VISIBLE);
                            line2choice.setVisibility(View.VISIBLE);
                            line3choice.setVisibility(View.VISIBLE);
                            line4choice.setVisibility(View.VISIBLE);
                            line5choice.setVisibility(View.VISIBLE);
                            line6choice.setVisibility(View.VISIBLE);

                            choice1Layout.setVisibility(View.VISIBLE);
                            choice2Layout.setVisibility(View.VISIBLE);
                            choice3Layout.setVisibility(View.VISIBLE);
                            choice4Layout.setVisibility(View.VISIBLE);
                            choice5Layout.setVisibility(View.VISIBLE);
                            choice6Layout.setVisibility(View.GONE);
                        }
                    }
                }

上面的代码是我更新 Ui 的地方。这里的数据库会立即更新。但是 Ui 没有相应更新。我更新了自定义适配器的 bindView() 中的 Ui。

您需要从 UI 线程创建并执行 AsyncTask。您在 AsyncTask 的 doInBackground() 上创建了它,它在非 UI 线程上工作。将其更改为

runOnUiThread(new Runnable() {
   @Override
   public void run() {
      PollReplyAsyncTask asyncTask = new PollReplyAsyncTask(activity, false, messageThread, messageThread.getUserId());
      asyncTask.execute();
   }
}

为什么?

来自线程规则下的文档 http://developer.android.com/reference/android/os/AsyncTask.html

  • The AsyncTask class must be loaded on the UI thread. This is done automatically as of JELLY_BEAN.

  • The task instance must be created on the UI thread.

  • execute(Params...) must be invoked on the UI thread.

  • Do not call onPreExecute(), onPostExecute(Result), doInBackground(Params...), onProgressUpdate(Progress...) manually.

  • The task can be executed only once (an exception will be thrown if a second execution is attempted.)

再详细一点就更好了

  1. 如果你的第二个异步任务有很多事情要做,并且你正在更新 onPostExecute() 方法中的 UI,那么显然 UI 不会更新直到任务完成。

  2. 您正在第二个异步任务中执行另一个异步任务。如果您在其中进行任何长时间操作,那也可能是问题所在。

因此,解决方案是您可以在加密和更新数据时显示进度条,或者您可以先更新 UI,然后加密并上传数据。