无法在Android上使用AsynckTask更新UI

时间:2016-11-25 17:32:12

标签: android-asynctask artificial-intelligence

我正在制作游戏2048的AI版本。在后台创建游戏树后,我想用asynctask更新UI。它暂时不起作用。 这是我在AsyncTask

中使用MainActivity.java;的地方
private class AsyncTaskRunner extends AsyncTask<Void, String, Void> {

    @Override
    protected Void doInBackground(Void... v) {
        try {
            Tree tree = new Tree(gameEngine);
            List<Node> path;

            Node root = new Node(gameEngine.grid.cells);

            tree.createInitialTree(root);
            path = ai.findPath(root);
            Node maxNode = path.get(path.size() - 1);

            for (Node node : path) {
                SystemClock.sleep(500);
                publishProgress(node.getDir());
            }

            while (!maxNode.myLose && (gameEngine.grid.areCellsAvailable(maxNode.getBoard()) || gameEngine.availableTileMatchLeft(maxNode)
                    || gameEngine.availableTileMatchRight(maxNode) || gameEngine.availableTileMatchUp(maxNode) ||
                    gameEngine.availableTileMatchDown(maxNode))) {
                tree = new Tree(gameEngine);
                tree.createTree(maxNode);

                path = ai.findPath(maxNode);

                for (Node node : path) {
                    SystemClock.sleep(500);
                    publishProgress(node.getDir());
                }

                maxNode = path.get(path.size() - 1);

            }
            System .out.println("You lose!!!");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    @Override
    protected void onProgressUpdate(String... direction) {
        switch (direction[0]) {
            case "left": onLeftSwipe();
                break;
            case "right": onRightSwipe();
                break;
            case "down": onDownSwipe();
                break;
            case "up": onUpSwipe();
                break;
        }
        super.onProgressUpdate(direction);
    }

    @Override
    protected void onPostExecute(Void v) {

    }
}

onCreate();

调用它
    AsyncTaskRunner runner = new AsyncTaskRunner();
    runner.execute();

使用publishProggress(path),我发送的列表path具有AI将执行的移动。但是当谈到onProggressUpdate()并执行onSwipeLeft()时,它不会更新游戏画面。我正确使用AsyncTask吗?谢谢你的帮助。

更新:现在正在更新UI,但不会等待publishProggress()完成。我该怎么做?

1 个答案:

答案 0 :(得分:1)

我不知道为什么你在super.onProgressUpdate(path);方法中注释了onProgressUpdate这句话。你不应该这样做。

由于您是第一次使用asynctask,我将为您提供一个非常简单的示例,可以从asynctask更新UI组件(textview和进度条)。

public class MainActivity extends ActionBarActivity {
    ProgressBar progressBar;
    TextView textOut1, textOut2, textOut3;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // required codes goes here
    }

    public class MyAsyncTask extends AsyncTask<Void, Integer, Void>{

        @Override
        protected void onPreExecute() {
            //In UI thread, you can access UI here
            super.onPreExecute();
            String s1 = textIn1.getText().toString();
            textOut1.setText(s1);
        }

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

            for(int i=0; i<=10; i++){
                SystemClock.sleep(1000);
                publishProgress(i);  //update UI in onProgressUpdate

                //Can GET from UI elements
                String s2 = textIn2.getText().toString();

                final String msgInBackGround = "doInBackground: " + i + " - " + s2;

                /*
                * Cannot direct SET UI elements in background thread
                * so do with runOnUiThread()
                */
                runOnUiThread(new Runnable(){
                    @Override
                    public void run() {
                    textOut2.setText(msgInBackGround);
                }});
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            //In UI thread, you can access UI here
            textOut3.setText("onPostExecute");
            super.onPostExecute(result);
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            //In UI thread, you can access UI here
            progressBar.setProgress(values[0]);
            super.onProgressUpdate(values);
        }

    }
}

希望它会对你有所帮助。您可以在网上找到完整的工作示例。请参阅它们以全面了解asynctask

UPDATE :为了在doInBackground()publishProgress()之间实现同步,您可以在某个全局对象上使用同步块,或者您可以使用简单标志来保持{的执行{1}}称为忙等待。

同步阻止

doInBackground()

忙碌等待 :( 不首选方式

使用标记protected List<Data> doInBackground(String... params) { synchronize(data) // data is some global object { // do some job 1 publishProgress(); // wait until the progress finish //do some job 3 } } protected void onProgressUpdate(Void... values) { synchronize(data) // data is the same global object { // do some job } } 然后调用发布进度。请忙于在_publishFinished = false;等待,如下所示。

doInBackground()

在onProgressUpdate调用结束时

if(!_publishFinish){
   Thread.Sleep(200); // busy waiting
}