Android 从OnPostExecute更新UI(异步)

Android 从OnPostExecute更新UI(异步),android,android-asynctask,android-4.2-jelly-bean,Android,Android Asynctask,Android 4.2 Jelly Bean,我有一个代表迷宫的数组。在UI上,迷宫表示为按钮的行和列。在异步任务的doInBackground方法中,我搜索了一条路径,并用通向目标的路径初始化了一个解决方案数组。我要做的是更新这些按钮的按钮文本,以显示通向目标的路径。我在OnPostExecute内部执行此操作。但是,它不起作用。它甚至不执行启用解决方案按钮的最后一行。我在哪里?在哪里 private void updateUI() { Button cell; TableRow row; do {

我有一个代表迷宫的数组。在UI上,迷宫表示为按钮的行和列。在异步任务的doInBackground方法中,我搜索了一条路径,并用通向目标的路径初始化了一个解决方案数组。我要做的是更新这些按钮的按钮文本,以显示通向目标的路径。我在OnPostExecute内部执行此操作。但是,它不起作用。它甚至不执行启用解决方案按钮的最后一行。我在哪里?在哪里

private void updateUI() {
    Button cell;
    TableRow row;

    do {
        row = (TableRow) (State.maze.getChildAt(solution.row));
        cell = (Button) (row.getChildAt(solution.col));
        cell.setText(State.pathCell);
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        solution = solution.next;
    } while (solution.next != null);
}

@Override
protected void onPostExecute(String result) {
    super.onPostExecute(result);
    updateUI();
    //Enable solution button
    State.solveResetButton.setEnabled(true);

}
更新: 我检查以确保解决方案变量包含解决方案,并且它确实包含有效数据。我还尝试删除睡眠,但没有效果

更新: Logcat输出(红色的)


solution.next的值不会在while循环中更新。这会导致无限循环,因此您的
updateUI()
方法永远不会停止执行

另外,
onPostExecute
作为
AsyncTask
的一部分始终在主线程上调用。您不想在主线程上使用
Thread.sleep
。这是一个获得ANR的好方法

关于如何做到这一点,有许多方法可能奏效。以汉德勒为主线考虑这样的事情:

private void updateUI() {
    Button cell;
    TableRow row;

    if (solution != null){
        row = (TableRow) (State.maze.getChildAt(solution.row));
        cell = (Button) (row.getChildAt(solution.col));
        cell.setText(State.pathCell);
        solution = solution.next;
        new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
            @Override
            public void run() {
                updateUI(); 
            }
        }, 100);
    }
}
您还可以通过使用
publishProgress
回调UI线程的新AsyncTask来完成此任务

private void updateUI(){
    new AsyncTask<Solution, Solution, Void>(){
        @Override
        protected Void doInBackground(Solution... solutions) {
            Solution solution = solutions[0];
            do {
                publishProgress(solution);
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                solution = solution.next;
            }
            while(solution.next != null);
            return null;
        }

        @Override
        protected void onProgressUpdate(Solution... values) {
            super.onProgressUpdate(values);
            Solution solution = values[0];
            row = (TableRow) (State.maze.getChildAt(solution.row));
            cell = (Button) (row.getChildAt(solution.col));
            cell.setText(State.pathCell);
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            //Enable solution button
            State.solveResetButton.setEnabled(true);
        }
    }.execute(solution);
}

@Override
protected void onPostExecute(String result) {
    super.onPostExecute(result);
    updateUI();
}
private void updateUI(){
新建异步任务(){
@凌驾
受保护的Void doInBackground(解决方案…解决方案){
溶液=溶液[0];
做{
出版进度(解决方案);
试一试{
睡眠(100);
}捕捉(中断异常e){
e、 printStackTrace();
}
solution=solution.next;
}
while(solution.next!=null);
返回null;
}
@凌驾
受保护的void onProgressUpdate(解决方案…值){
super.onProgressUpdate(值);
溶液=数值[0];
row=(TableRow)(State.maze.getChildAt(solution.row));
单元格=(按钮)(row.getChildAt(solution.col));
cell.setText(State.pathCell);
}
@凌驾
受保护的void onPostExecute(void避免){
super.onPostExecute(避免);
//启用解决方案按钮
State.solveResetButton.setEnabled(true);
}
}.执行(解决方案);
}
@凌驾
受保护的void onPostExecute(字符串结果){
super.onPostExecute(结果);
updateUI();
}

您的logcat中是否存在任何异常?如果您能够调试它,将有一个简单的解决方案。您可以发布所有代码吗?您是否在串行执行器上运行AsyncTask?这是一个无限循环吗?看起来您从未更改过解决方案。下一步,请在do循环中更改条件。或者next总是转到下一个值直到null吗?@jacobhyphenated该死,我错过了那个值。但是它仍然不会更新按钮。那么,延迟更新按钮文本的正确方法是什么,以便一次只更新一个按钮?现在,它不会延迟,而是一次更新所有按钮。@user3273345我已经编辑了上面的答案,以包含一些代码示例。这只是你可以选择的两个选项。有很多方法可以完成你想要做的事情。
private void updateUI(){
    new AsyncTask<Solution, Solution, Void>(){
        @Override
        protected Void doInBackground(Solution... solutions) {
            Solution solution = solutions[0];
            do {
                publishProgress(solution);
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                solution = solution.next;
            }
            while(solution.next != null);
            return null;
        }

        @Override
        protected void onProgressUpdate(Solution... values) {
            super.onProgressUpdate(values);
            Solution solution = values[0];
            row = (TableRow) (State.maze.getChildAt(solution.row));
            cell = (Button) (row.getChildAt(solution.col));
            cell.setText(State.pathCell);
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            //Enable solution button
            State.solveResetButton.setEnabled(true);
        }
    }.execute(solution);
}

@Override
protected void onPostExecute(String result) {
    super.onPostExecute(result);
    updateUI();
}