在后台运行计算任务时的进度对话框(AsyncTask)

时间:2013-05-26 10:29:31

标签: java android

我很困惑,我正在尝试两天在图像上制作动画,而我的引擎正在考虑移动(这是一款游戏应用)。我在AsyncTask对象中执行chooseMove()方法,因为它是一个有点繁重的递归函数,可能需要一些时间,而且我还想在引擎思考时旋转沙漏图像。我试图以我知道的方式做到这一点:另一个AsyncTask,Android自己的动画类,处理程序等。但无论我做什么,似乎我无法使它发挥作用。如果我尝试同时执行两个线程,它只执行其中一个,并且同样的事情发生在android自己的动画类中。所以我试图使用进度对话只是为了看到我没有变得疯狂,并猜猜是什么..同样的问题!我在onPreExecute()中显示进度对话框,但doInBackgroun()永远不会完成!由于某种原因,进度对话框控制整个应用程序。我该怎么办?我虽然进度对话框是针对这种事情的。 THX!

编辑:这是我的异步任务类的代码。正如您所看到的,我在onPreExecute()中显示了一个进度对话框,并在onPostExecute中将其解除。但onPost永远不会被调用,因为doInBackground()永远不会被调用。

protected void onPreExecute() {
    super.onPreExecute();
    activity.setPlaying(true);
    if (android.os.Build.VERSION.SDK_INT >android.os.Build.VERSION_CODES.GINGERBREAD) {
        // only for gingerbread and newer versions
        activity.invalidateOptionsMenu();
    }
    progressDialog = new ProgressDialog(activity);
    progressDialog.setMessage("Thinking...");
    progressDialog.setIndeterminate(true);
    progressDialog.setCanceledOnTouchOutside(false);
    progressDialog.show();
}


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

    int engineWin = board.takeWin(board.getBoard(), engine.getNumberOfEngine());
    int opponentWin = board.takeWin(board.getBoard(), engine.getNumberOfOpponent());

    if(engineWin!=-1){
        try{
            Thread.sleep(500);
        }
        catch(Exception e){}
        return engineWin;
    }
    else if(opponentWin!=-1){
        try{
            Thread.sleep(500);
        }
        catch(Exception e){}
        return opponentWin;
    }
    else{

        if(engine.isEnginesTurn()&&!Board.checkGameOver(board.getBoard())){
            int[] newBoard = new int[42];
            System.arraycopy(board.getBoard(), 0, newBoard, 0, 42);
            return engine.chooseMove(engine.isEnginesTurn(),newBoard,-500001,500001,0,4).getMove();
        }

        else{
            return -1;
        }
    }

}





@Override
protected void onProgressUpdate(Void... values) {
    super.onProgressUpdate(values);

}


@Override
protected void onPostExecute(Integer result) {
    super.onPostExecute(result);
    progressDialog.dismiss();

    if(result!=-1){

        ballAnimTask = new BallAnimTask(activity,boardView,board,engine);
        ballAnimTask.execute(findSlotNumberByIndex(result));
    }

}

这是我在doInBackground()中调用的递归chooseMove()。在我试图显示进度对话框之前,一切正常。此功能或任何其他功能没有问题。只有当我试图同时做动画或对话时,我才会遇到问题。 chooseMove()实际上是在另一个类上,我只是从AsyncTask中调用它。也许这就是问题?

public Best chooseMove(boolean side,int[]board,int alpha,int beta,int depth,int maxDepth){
    Best myBest = new Best();
    Best reply;
    int num;
    if(Board.checkGameOver(board)||depth==maxDepth){
        myBest.setScore(returnPositionScore(board));
        return myBest;
    }
    if(side){
        myBest.setScore(alpha);
        num = numberOfEngine;
    }
    else{
        myBest.setScore(beta);
        num = numberOfOpponent;
    }
    ArrayList<Integer> availableMoves = new ArrayList<Integer>();
    availableMoves = searchAvailableMoves(board);
    for(int move:availableMoves){
        board[move] = num;
        reply = chooseMove(!side,board,alpha,beta,depth+1,maxDepth);
        board[move] = 0;
        if(side&&reply.getScore()>myBest.getScore()){
            myBest.setMove(move);
            myBest.setScore(reply.getScore());
            alpha = reply.getScore();
        }
        else if(!side&&reply.getScore()<myBest.getScore()){
            myBest.setMove(move);
            myBest.setScore(reply.getScore());
            beta = reply.getScore();
        }
        if(alpha>=beta){
            return myBest;
        }
    }
    return myBest;
}

2 个答案:

答案 0 :(得分:0)

如果您想在AsyncTask内执行任何与UI相关的操作,则需要调用AsyncTask publishProgress方法。这将在主UI线程中调用onProgressUpdate回调,因此您可以安全地在那里执行与UI相关的操作。

显然,onProgressUpdate中的任何代码都无法阻止,因为您现在回到主UI线程中。但是,您可以更新状态栏,例如,等待下一次onProgressUpdate回调再次更新之前。

答案 1 :(得分:0)

只是为了一些灵感,这里是我成功使用的通用代码格式,显示了一个水平进度条,在后台任务运行时进行更新。我知道它没有回答您的确切问题,但我希望它能帮助您找到解决方案。

ProgressDialog myProgressDialog;

private void someFunctionThatStartsTheAsyncTask()
{
    new myBackgroundTask.execute(someIntegerArgument);
}

private class myBackgroundTask extends AsyncTask<Integer, Integer, Boolean>
{
    protected void onPreExecute()
    {
        myProgressDialog = new ProgressDialog(myContext);
        myProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        myProgressDialog.setTitle("Doing something in background...");
        myProgressDialog.setMessage("Please wait...");
        myProgressDialog.setCancelable(false);
        myProgressDialog.setIndeterminate(false);
        myProgressDialog.setMax(100);
        myProgressDialog.setProgress(0);
        myProgressDialog.show();
    }

    protected Boolean doInBackground(Integer... params)
    {
        int someVariable = params[0];
        boolean success;

        for (whatever loop conditions)
        {
            // some long-running stuff, setting 'success' at some point
            ...

            publishProgress(newPositionForProgressBar);
        }

        return success;
    }

    protected void onProgressUpdate(Integer... progressPosition)
    {
        myProgressDialog.setProgress(progressPosition[0]);
    }

    protected void onPostExecute(Boolean result)
    {
        myProgressDialog.dismiss();

        if (result)
        {
            //doInBackground returned true
        }
        else
        {
            //doInBackground returned false
        }
    }
}