简体   繁体   中英

Progress dialog while running computation task in background (AsyncTask)

I am very confused, i am trying for two days to make animation on an image while my engine is thinking of a move (this is a game app). I execute the chooseMove() method inside AsyncTask object because it is a little heavy recursive function that may take some time,and also i want to rotate an hourglass image while the engine is thinking. and i tried to do it every way i know: another AsyncTask, Android's own animation class,handlers etc'. but no matter what i do it seems that i can't make it work. if i try to execute two threads at the same time,it only executes one of them, and the same thing happens with android own animation class. so i tried to use a progress dialog just to see that i am not getting crazy,and guess what.. same problem! I show the progress dialog in the onPreExecute() ,but the doInBackgroun() never gets done! the progress dialog take control over the whole app for some reason. how should i do it? i though that the progress dialog is meant for this kind of things. thx!

EDIT: this is the code of my async task class. as you can see, i am showing a progress dialog in the onPreExecute() ,and dismissing it in the onPostExecute. but the onPost never gets called because the doInBackground() never gets called either.

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));
    }

}

this is the recursive chooseMove() i am calling in doInBackground(). before i tried to show the progress dialog,everything worked just fine. there is no problem with this function or any other function for that matter. only when i tried to do animations or dialogs at the same time,i got issues. the chooseMove() is physically on another class and i am only calling it from the AsyncTask. maybe this is the problem??

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;
}

If you want to perform any UI related operation from within an AsyncTask you need to call the AsyncTask publishProgress method. This will invoke an onProgressUpdate callback in the main UI thread and so you can then safely perform your UI related operations there.

Obviously any code in the onProgressUpdate can't block, though, since you are now back in the main UI thread. But you can update a status bar, for example, and then wait for the next onProgressUpdate callback before you update it again.

Just for some inspiration, here is the general code format that I have used successfully to show a horizontal progress bar which updates while a background task is running. I know it doesn't answer your exact question, but I hope it helps you to find your solution.

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
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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