"Busy" progress dialog causes strange code processing
Let me sum up the situation for you:
- I have a button (btnChooseEp), and when you press it an AlertDialog appears.
- When something is picked in the AlertDialog, three if statements must be evaluated.
- While they are being evaluated, a ProgressDialog appears. It indicates that the app is "busy".
- After the evaluation of these statements, the ProgressDialog must disappear.
My problem is described beneath the code.
The entire code block is shown here:
ProgressDialog getTracklistProgressDialog = null;
...
Button btnChooseEp = (Button)findViewById(R.id.btnChooseEp);
btnChooseEp.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
final AlertDialog.Builder builder = new AlertDialog.Builder(GA.this);
builder.setTitle(getText(R.string.chooseEpisode));
builder.setItems(episodes, new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, final int pos)
{
getTracklistProgressDialog = ProgressDialog.show(GA.this, "Please wait...",
"Retrieving tracklist...", true);
new Thread()
{
public void run()
{
try
{
String str1, epURL;
if(pos < 9)
{
str1 = getResources().getString(R.string.epNo1);
epURL = String.format开发者_开发知识库(str1, pos+1);
setTracklist(epURL, tracklist);
}
else if(pos < 100)
{
str1 = getResources().getString(R.string.epNo2);
epURL = String.format(str1, pos+1);
setTracklist(epURL, tracklist);
}
else if(pos >= 100)
{
str1 = getResources().getString(R.string.epNo3);
epURL = String.format(str1, pos+1);
setTracklist(epURL, tracklist);
}
}
catch(Exception e)
{}
// Remove progress dialog
getTracklistProgressDialog.dismiss();
}
}.start();
}
});
AlertDialog alertDialog = builder.create();
alertDialog.show();
}
});
Not sure if needed, but here is the code for the function setTracklist:
public void setTracklist(String string, TextView tv)
{
try
{
tv.setText(getStringFromUrl(string));
}
catch(Exception e)
{
e.printStackTrace();
}
}
And the code for the function getStringFromUrl can be seen here: http://pastebin.com/xYt3FwaS
Now, the problem: Back when I didn't implement the ProgressDialog thing (which I have from here, btw: http://www.anddev.org/tinytut_-_displaying_a_simple_progressdialog-t250.html), it worked fine - the setTracklist function retrieves a string from a text file on the internet, and sets the text to a TextView. Now, when I have added the ProgressDialog code, and put the original code into the try statement, only a very little part of the text file is added to the TextView - approximately 22-24 characters, not more. The "busy" ProgressDialog shows up just fine. It worked perfectly before; it was more than capable of loading more than 1300 characters into the TextView. I don't know if it has anything to do with the thread - I have Googled a lot and found no answer.
So, how do I get it to load in all data instead of just a small part?
(By the way, I would love to be able to set the line "setTracklist(epURL, tracklist);" beneath all of the if statements, but then it says it can't resolve "epURL". Seems stupid to write the same line 3 times!)
Updated 25/1 with current code:
final Handler uiHandler = new Handler();
final Button btnChooseEp = (Button)findViewById(R.id.btnChooseEp);
btnChooseEp.setEnabled(false);
btnChooseEp.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
builder.setTitle(getText(R.string.chooseEpisode));
builder.setItems(episodes2, new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, final int pos)
{
replay.setVisibility(View.VISIBLE);
replayWeb.setVisibility(View.VISIBLE);
getTracklistProgressDialog = ProgressDialog.show(GA.this, "Please wait...",
"Retrieving tracklist...", true);
new Thread()
{
public void run()
{
try
{
String str1, epURL;
if(pos < 9)
{
str1 = getResources().getString(R.string.gaEpNo1);
epURL = String.format(str1, pos+1);
setTracklist2(epURL, tracklist);
}
else if(pos < 100)
{
str1 = getResources().getString(R.string.gaEpNo2);
epURL = String.format(str1, pos+1);
setTracklist2(epURL, tracklist);
}
else if(pos >= 100)
{
str1 = getResources().getString(R.string.gaEpNo3);
epURL = String.format(str1, pos+1);
setTracklist2(epURL, tracklist);
}
}
catch(Exception e)
{}
// Remove progress dialog
uiHandler.post(new Runnable()
{
public void run()
{
getTracklistProgressDialog.dismiss();
}
}
);
}
}.start();
}
});
AlertDialog alertDialog = builder.create();
alertDialog.show();
}
});
public void setTracklist2(final String string, final TextView tv)
{
try
{
uiHandler.post(
new Runnable()
{
public void run()
{
try
{
tv.setText(getStringFromUrl(string));
}
catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}
}
});
}
catch(Exception e)
{
e.printStackTrace();
}
}
Notes: "replay" and "replayWeb" are just two TextView's. "btnChooseEp" is enabled when another button is pressed.
My guess is that you are getting bizarre behavior because you are invoking a ui method on a non-ui thread.
getTracklistProgressDialog.dismiss();
must be executed on a ui thread. My guess is that it is crashing and your thread is crashing then leaving some of your resources in a bad state. This would explain why you get a varying amount of characters.
I would try creating a final Handler in your onCreate method which would get bound to the uiThread. In that thread, you can then call
uiHandler.post(
new Runnable() {
public void run(){
getTracklistPRogressDialog.dismiss();
}
}
);
This is quick, so it may not be syntactically correct, check your ide.
This is the best i can get from what you've posted. If you post more of the code I can try to run it to give you more help.
Update:
I think I found your problem:
The idea of having another thread is to do the long running work there, but what we have right now actually does the long running work on the ui thread, the opposite of our goal. What we need to do is move the call to getStringFromUrl(url)
from the setTracklist call up into the thread. I would rewrite setTracklist as follows:
public void setTracklist(String tracklistContent, TextView tv)
{
try
{
runOnUiThread(
new Runnable() {
public void run() {
tv.setText(tracklistContent);
}
});
}
catch(Exception e)
{
e.printStackTrace();
}
}
Then in your inner onClick method, do this:
public void onClick(DialogInterface dialog, final int pos)
{
getTracklistProgressDialog = ProgressDialog.show(GA.this, "Please wait...",
"Retrieving tracklist...", true);
new Thread()
{
public void run()
{
try
{
String str1, epURL;
if(pos < 9)
{
str1 = getResources().getString(R.string.epNo1);
epURL = String.format(str1, pos+1);
String tlContent = getStringFromUrl(epUrl);
setTracklist(epURL, tracklist);
}
else if(pos < 100)
{
str1 = getResources().getString(R.string.epNo2);
epURL = String.format(str1, pos+1);
String tlContent = getStringFromUrl(epUrl);
setTracklist(epURL, tracklist);
}
else if(pos >= 100)
{
str1 = getResources().getString(R.string.epNo3);
epURL = String.format(str1, pos+1);
String tlContent = getStringFromUrl(epUrl);
setTracklist(epURL, tracklist);
}
}
catch(Exception e)
{}
// Remove progress dialog
getTracklistProgressDialog.dismiss();
}
}.start();
}
I'm so, we make the call to the web service/url before we regain ui thread execution. The long running internet retrieval runs on the bg thread and then the ui update happens on the ui thread. Think this should help.
精彩评论