简体   繁体   English

使用Asynctask在Android中获取更新的UI

[英]Getting Updated UI in Android using Asynctask

I am building a Maze game in android (for a school assignment), and am having trouble getting an automated driver to work. 我正在用android构建迷宫游戏(用于学校作业),但无法让自动驱动程序正常工作。 The Game works fine for manual maze exploration, but when I try to use a driver to explore the maze the graphics don't update to the view. 游戏对于手动迷宫探索工作正常,但是当我尝试使用驱动程序探索迷宫时,图形不会更新到视图。 I know I have to use a handler somehow, but I am a bit lost on that matter. 我知道我必须以某种方式使用处理程序,但是在这件事上我有点迷茫。 A few codeblocks below might help make things more clear. 下面的一些代码块可能有助于使事情更加清楚。

This is in PlayActivity: 这是在PlayActivity中:

class RobotTask extends AsyncTask<Integer , Void , Void> {

    @Override
    protected Void doInBackground(Integer... params) {
        robotDriver.setView(mazeView);
        try {

            if(robotDriver.drive2Exit()) {
                Intent finishIntent = new Intent(PlayActivity.this, FinishActivity.class);
                startActivity(finishIntent);
            }
        } catch (Exception e) {
            Toast.makeText(PlayActivity.this, "Robot Ran Out Of Power", Toast.LENGTH_SHORT).show();
            Intent intent = new Intent(PlayActivity.this , AMazeActivity.class);
            NavUtils.navigateUpTo(PlayActivity.this, intent);

        }
        return null;
    }

And then robotDriver.drive2Exit() calls a specific exploration algorithm which moves the robot, this code is below (not all of it, just where I assume I need a change): 然后,robotDriver.drive2Exit()调用特定的探索算法来移动机器人,该代码在下面(并非全部,只是我认为需要更改的地方):

if(forward)
            try {
                Thread.sleep(250);
                robot.move(1, true);
                this.mazeView.postInvalidate();
            } catch (HitObstacleException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();                        }
else {
            try {

                robot.rotate(90); // turn then move
                this.mazeView.postInvalidate();
                Thread.sleep(250);
                robot.move(1, true);
                this.mazeView.postInvalidate();
                Thread.sleep(500);
            } catch (HitObstacleException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    break;
                }
            }   

robot.move() and rotate() move the robot through the maze, and then update the two drawers classes I use to present the firstpersonview. robot.move()和rotate()在迷宫中移动机器人,然后更新我用来展示firstpersonview的两个抽屉类。 These updates update the bitmap in mazeView, where I would hope that the postInvalidate() call would then feed these updates to the viewer. 这些更新更新了mazeView中的位图,我希望在那里可以通过postInvalidate()调用将这些更新提供给查看器。

Any thoughts would be helpful. 任何想法都会有所帮助。

I don't think you can start the activity directly from the doInBackground() method and you can't update view from the worker thread. 我认为您不能直接从doInBackground()方法开始活动,也无法从辅助线程更新视图。 All these operations (Intent, Toast) have to be done in the UI thread 所有这些操作(Intent,Toast)都必须在UI线程中完成

I think you problem is that you're trying to do some process that should update your UI thread on a thread that is not your UI thread. 我认为您的问题是,您正在尝试执行一些应在不是您的UI线程的线程上更新UI线程的过程。 Either you want this process to run on your UI thread and update it accordingly, or you don't. 您是否希望此过程在您的UI线程上运行并相应地进行更新,或者您不希望这样做。 According to the documentation postInvalidate() causes an invalidate to happen on a subsequent cycle through the event loop. 根据文档, postInvalidate()会导致在事件循环的后续周期中发生无效。 So you should call invalidate() on the mazeview in your UI thread. 因此,您应该在UI线程中的mazeview上调用invalidate()。 To fix this you have to reorganize your code to something like the following. 要解决此问题,您必须将代码重新组织为以下内容。 Make an async class to do your robot's moving caclulations: 制作一个异步类来执行机器人的移动计算:

    private final Robot robot;
public class RobotWorker extends AsyncTask<Void, Void, Void> {
    @Override
    protected Void doInBackground(Void... params) {
        //implement locking / synchronization here
        if( forward ) {//pas as a param
            try{
                Thread.sleep(250);
                robot.move(1,true);
            }catch( HitObstacleException e ){
                e.printStackTrace();
            }
        }
    else{
            try{
                robot.rotate(90);
                Thread.sleep(250);
            }catch( HitObstacleException e ){
                e.printStackTrace();
            }
        }
        return null;
    }
}

and on your UI thread do something like this 在你的UI线程上做这样的事情

public void myRobotMover(){
    //implement locking / synchroniztion
    new RobotWorker().execute();
    mazeView.invalidate();
}

Again, you'll have to implement some synchronization and locking. 同样,您将必须实现一些同步和锁定。 Learn how to here. 在这里了解如何。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM