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
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
Figured it out, I had a runaway method going on the UI thread that i did not notice
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).
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.
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;
}
}
来源:https://stackoverflow.com/questions/11916098/progress-dialog-ui-freezes-slow