Progress dialog UI Freezes/Slow
Asked Answered
P

5

10

I have a progress dialog that I use for a part in my program where I do a time intensive operation in the background but when the dialog gets displayed the UI or spinner icon freezes/slow/hesitates making the program appear as if it froze. In my onPostExecute of my AsyncTask I dismiss the dialog.

Why would this happen since I am doing all the work in the background?

here is my code

pDialog = ProgressDialog.show(FullGame.this,"Starting New Game","Please Wait...", true);
new StartNewGame().execute(); 

    private class StartNewGame extends AsyncTask<Void,Void,Boolean>{

    @Override
    protected Boolean doInBackground(Void... params) {
        try{
            ContentValues values = new ContentValues();
            Cursor c = getContentResolver().query(Games.PART1_URI,new String[] {Games.PART1_NUM},
                    Games.PART1_GAME_ID+"="+gameID+" AND "+Games.PART1_FRAME_NUM+"="+10,null,null);
            c.moveToFirst();
            String num = c.getString(0);
            int part1 =0;
            if(num.equals("-")){
                part1=0;
            }else{
                part1=Integer.parseInt(num);
            }

            c = getContentResolver().query(Games.PART2_URI,new String[] {Games.PART2_NUM},
                    Games.PART2_GAME_ID+"="+gameID+" AND "+Games.PART2_FRAME_NUM+"="+10,null,null);
            c.moveToFirst();
            int part2 = 0;
            if(num.equals("-")){
                part2=0;
            }else{
                part2=Integer.parseInt(num);
            }

            c = getContentResolver().query(Games.PART3_URI,new String[] {Games.PART3_NUM},
                    Games.PART3_GAME_ID+"="+gameID,null,null);
            c.moveToFirst();
            int part3 = 0;
            if(num.equals("-")){
                part3=0;
            }else{
                part3=Integer.parseInt(num);
            }

            if(part1 == 10){
                values.clear();
                values.put(Games.STRIKES_FRAME_NUM,10);
                values.put(Games.STRIKES_BOWLER_ID,bowlerClickedID);
                values.put(Games.STRIKES_GAME_ID,gameID);
                getContentResolver().insert(Games.STRIKES_URI, values);
            }
            if(part2 == 10){
                values.clear();
                values.put(Games.STRIKES_FRAME_NUM,10);
                values.put(Games.STRIKES_BOWLER_ID,bowlerClickedID);
                values.put(Games.STRIKES_GAME_ID,gameID);
                getContentResolver().insert(Games.STRIKES_URI, values);
            }
            if(((part2+part3) == 10) && !score.checkSpare(10)){
                values.clear();
                values.put(Games.SPARES_BOWLER_ID,bowlerClickedID);
                values.put(Games.SPARES_FRAME_NUM,10);
                values.put(Games.SPARES_GAME_ID,gameID);
                getContentResolver().insert(Games.SPARES_URI, values);
            }
            if(part3 == 10){
                values.clear();
                values.put(Games.STRIKES_FRAME_NUM,10);
                values.put(Games.STRIKES_BOWLER_ID,bowlerClickedID);
                values.put(Games.STRIKES_GAME_ID,gameID);
                getContentResolver().insert(Games.STRIKES_URI, values);
            }
        c.close();
        }catch(Exception e){
            Log.d("FullGame",e.toString());
        }

        Date date = new Date(System.currentTimeMillis());
        DateFormat df = new SimpleDateFormat("MM/dd/yyyy");
        String newDate = df.format(date);

        ContentValues values = new ContentValues();
        values.put(Games.GAMES_BOWLER_ID,bowlerClickedID);
        values.put(Games.GAMES_TEAM_ID,1);
        values.put(Games.GAMES_DATE,newDate);
        values.put(Games.GAME_SEASON, pref.getLong(Preferences.SELECTED_SEASON, 1));
        values.put(Games.GAMES_TOURNAMENT_ID, tournamentID);
        Uri uri = getContentResolver().insert(Games.GAMES_URI, values);
        gameID = ContentUris.parseId(uri);
        int gameid = Integer.valueOf(String.valueOf(gameID));
        values.clear();
        Cursor cName = getContentResolver().query(BowlersDB.CONTENT_URI,new String[] {BowlersDB.FIRST_NAME},BowlersDB.ID+"="+bowlerClickedID,null,null);
        cName.moveToFirst();
        String name = cName.getString(0);
        for(int i = 0;i<10;i++){
            int num = i+1;
            values.put(Games.NAMES_FRAME_NUM,num);
            values.put(Games.NAMES_GAME_ID,gameid);
            values.put(Games.NAMES_NAME,name);
            getContentResolver().insert(Games.NAMES_URI, values);
            names(i,name);
            values.clear();
            values.put(Games.PART1_FRAME_NUM,num);
            values.put(Games.PART1_NUM,"0");
            values.put(Games.PART1_GAME_ID,gameid);
            getContentResolver().insert(Games.PART1_URI, values);
            values.clear();
            values.put(Games.PART2_FRAME_NUM,num);
            values.put(Games.PART2_NUM,"0");
            values.put(Games.PART2_GAME_ID,gameid);
            getContentResolver().insert(Games.PART2_URI, values);
            values.clear();
            values.put(Games.TOTALS_FRAME_NUM,num);
            values.put(Games.TOTALS_FRAME_TOTAL,"0");
            values.put(Games.TOTALS_GAME_ID,gameid);
            getContentResolver().insert(Games.TOTALS_URI, values);
            values.clear();
            values.put(Games.POCKETS_BOWLER_ID,bowlerClickedID);
            values.put(Games.POCKETS_FRAME_NUM,i);
            values.put(Games.POCKETS_GAME_ID,gameID);
            values.put(Games.POCKETS_TEAM_ID, teamSelectedID);
            values.put(Games.POCKETS_TOURNAMENT_ID, tournamentID);
            values.put(Games.POCKETS_NUM, 0);
            values.put(Games.POCKETS_SEASON, pref.getLong(Preferences.SELECTED_SEASON, 1));
            getContentResolver().insert(Games.POCKETS_URI, values);
            values.clear();
        }

        values.put(Games.PART3_GAME_ID,gameid);
        values.put(Games.PART3_NUM,"0");
        getContentResolver().insert(Games.PART3_URI, values);
        cName.close();
        part1Array = new int[10];
        part2Array = new int[10];
        totalsArray = new int[10];
        part3 = 0;
        mPinsUp = new ArrayList<Long>();
        mPinsUp.add((long) 1);
        mPinsUp.add((long) 2);
        mPinsUp.add((long) 3);
        mPinsUp.add((long) 4);
        mPinsUp.add((long) 5);
        mPinsUp.add((long) 6);
        mPinsUp.add((long) 7);
        mPinsUp.add((long) 8);
        mPinsUp.add((long) 9);
        mPinsUp.add((long) 10);
        return true;
    }

    protected void onPostExecute(Boolean result){
            pDialog.dismiss();
    }

}

UPDATE: running through the code in debug mode last night it seems to start to do it in the for loop but still all of this is done in a separate thread and I am only inserting values into my database

UPDATE 2 if I comment out the for loop the progress dialog gets displayed for less than a second so even though I am doing everything in an AsyncTask the inserts must still run in the UI thread

Proser answered 11/8, 2012 at 15:55 Comment(7)
Are you doing this on the main thread or the ui thread. There are other topics about this on SO, maybe they will help. #3653060Auckland
well as you can see it is an AsyncTask so it would be in another threadProser
where is your onPreExecute section? Also you can put all the code in doInBackground into a method as it should all execute in the new thread anyway, and make all this easier to read. Also what hardware are you testing on?Smilax
I don't have a onPreExecude method is it even needed?. I tested this on Galaxy Nexus, Nexus 7 and Samsung Galaxy Tab 10.1 all with the same resultsProser
I also had a problem like this, due to my UI thread being blocked. I'd suggest you have a look if you are possibly blocking it somewhere in your code.Katiekatina
@Luke this is all done on a button click after everything has been loaded so basically the program is sitting idle at this timeProser
perhaps this question and its answers will help you linkShowker
P
2

Figured it out, I had a runaway method going on the UI thread that i did not notice

Proser answered 17/8, 2012 at 2:53 Comment(0)
K
2

This probably happens because your background thread consumes 100% of device CPU. When CPU is busy processing one thread, UI thread won't be updated and therefore you see it as frozen

Try to detect what's the most aggressive operation by removing parts of code from your doInBackground and running the app again. Also try to see how it performs when device is not plugged via USB - this some times provides weird results

Kimberleekimberley answered 16/8, 2012 at 12:12 Comment(1)
the problem is in the for loop where it is inserting fields into my database. If i comment that out it shows the progress dialog for less than a second so apparently even though I am doing everything in an AsyncTask the inserts must still be running in the UI threadProser
P
2

Figured it out, I had a runaway method going on the UI thread that i did not notice

Proser answered 17/8, 2012 at 2:53 Comment(0)
M
0

You are using the ProgressDialog wrong.

You need to add a onPreExecute method, and there you define and show your ProgressDialog. Then doInBackground is performed on another thread, and eventually in onPostExecute you dismiss the dialog.

Here's a simple example:

class RefreshChanges extends AsyncTask<String, Void, String> {
        private ProgressDialog mProgressDialog = new ProgressDialog(
                mContext);

        @Override
        protected void onPreExecute() {
            mProgressDialog.setTitle("Whatever title");
            mProgressDialog.setMessage("Whatever message");
            mProgressDialog.show();
        }

        protected String doInBackground(String... strings) {
            // Do whatever processing you want...
            return "";
        }

        protected void onPostExecute(String result) {
            mProgressDialog.dismiss();
            mProgressDialog = null;
        }
    }
    new RefreshChanges().execute();

By the way, I also recommend you not to use hardcoded strings. Instead, you can go to the strings.xml file under res\values\ and define a string. Then in your code, you can use either getString(R.string.yourStringId) or R.string.yourStringId. It depends whether the method accepts Id's or not (Methods that accept Id's, actually perform getString with the Id you sent it).

Masked answered 14/8, 2012 at 14:29 Comment(3)
But what is the difference if I use onPostExecute or just declare the progress dialog right before i start the AsyncTask? I just dont see how that would fix the problem since both are in the UI thread correct?Proser
@Proser I honestly don't know the exact difference (but by saying this, you are rising the question why onPostExecute is needed at all). It seems there is a difference, because I had the same problem you are experiencing. I also defined the ProgressDialog out of the AsyncTask, and when I moved inside, it worked perfectly smoothly. I suggest you try it and see. It should workMasked
I threw it in the onPreExecute and it still did the same thing unfortunatelyProser
I
0

I have implemented the dialog this way with success.

private ProgressDialog progress;

private class AsynTask extends AsyncTask<Void, Void, Void> {

        @Override
        protected void onPreExecute() {
           progress = ProgressDialog.show(context, "", "Please wait...", true);

       }

        @Override
        protected void onPostExecute(Void params) {
             if (progress.isShowing()) 
                  progress.dismiss();

       }

        @Override
        protected Void doInBackground(Void... arg0) {
             // Do some work
             return null;
       }
 }
Incogitable answered 16/8, 2012 at 2:56 Comment(0)
K
0

i don't see any fault in your code, but you have to understand that only writing code in another thread does not means it will get another processor. if your device is having single core processor it does time slicing and does work in round robin way. if your device has multiple cores it will do actual multiple threading. so if you have single core processor it will show you some lag in progress bar.

Kaunas answered 16/8, 2012 at 11:53 Comment(1)
all devices tested have multi coresProser

© 2022 - 2024 — McMap. All rights reserved.