i am writing here to ask you a litlle question about the progress dialog.
In fact, i call web service in my application, the progress dialog works very well.
But when i change the date of my object to do the call of my web service,
the progress dialog appear, the results are receiveid. AND automatically, there is a new call of the web service and the progress dialog didn't dissmiss :-/
On my server JBoss, i can see the calls from my application.
At the first create of my activity i have one call.
But at the second call, when i changed the date, there are two call. i don't know why because when i change one of my spinner its works fine, the web service is call and returns the results.
I call the web service in a asynctask. I do nothing with the progress dialog in the asynctask.
Here is the method where i call the progress dialog
public void callWebService()
{
myProgressDialog = ProgressDialog.show(OverviewMoney.this,"", "Récupération liste des positions cash",true);
final Runnable runInUIThread = new Runnable() {
public void run() {
setListView();
}
};
new Thread() {
#Override public void run()
{
loadListMoney();
myProgressDialog.dismiss();
uiThreadCallback.post(runInUIThread);
myProgressDialog= null;
}
}.start();
}
The method loadListMoney call my web service in a asynctask and the method setListView put my resultList in an adapter to print the list on a list view.
Thanks in advance :-) (And sorry for my english)
Try this
public void callWebService()
{
if (myProgressDialog != null) myProgressDialog.dismiss();
myProgressDialog = ProgressDialog.show(OverviewMoney.this,"", "Récupération liste des positions cash",true);
final Runnable runInUIThread = new Runnable() {
public void run() {
setListView();
}
};
new Thread() {
#Override public void run()
{
loadListMoney();
myProgressDialog.dismiss();
uiThreadCallback.post(runInUIThread);
myProgressDialog= null;
}
}.start();
}
According to my understanding, when this function is called twice 1st time it will start progress dialog and quickly another function call is placed so without dismissing previous progress dialog you were creating one more progress dialog. So that was the main cause of it.
Related
My application processes some images in a thread and meanwhile it shows a dialog with a progressbar.
progressDialog = new ProgressDialog(Activity.this);
progressDialog.setProgressStyle(size);
progressDialog.show();
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
for(int i = 0; i < size; i++{
//process images
runOnUiThread(new Runnable() {
#Override
public void run() {
progressDialog.setProgress(i);
}
});
}
}
});
thread.start();
Now, if a rotation occurs I do
#Override
protected void onDestroy() {
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
super.onDestroy();
}
and in onCreate I recreate the dialog. But the thread don't changes the progressbar of this new dialog.
After rotation the Activity (or the Fragment) in which this dialog is shown is discarded and a new one is created.
You re-create the dialog in the new Activity, but the thread you started updates the dialog in the old one (the fact that this thread has a reference to the old dialog also constitutes a memory leak).
I'd suggest that you do the following:
Implement some ImageProcessor class and put an instance of it in Application object.
Make ImageProcessor class observable and notify the listeners about the progress.
Get a reference to this object in Activity and subscribe to notifications in onStart() (and unsubscribe in onStop()).
When status update notifications arrive - update the progress indication
Using this approach you'll have the processing logic encapsulate in a special object that survives rotation, and different components can invoke its methods and subscribe to notifications from it.
I have an Android application with an AsyncTask which is responsible for downloading a file from the internet. This AsyncTask is executed when clicking on an item in a Listview. So I have a custom adapter and in the OnItemClickListener of the Listview, I start the download and execute the AsyncTask.
Now, my adapter contains the following code to start the AsyncTask named FileDownloader:
#Override
public void onClick(View view) {
try {
FileDownloader fd = new FileDownloader(activity);
// some irrelevant code here
String filepath = fd.execute("http://myurl.com/img.png", PDFFileName, GameHistoryAdapter.this.gameInfo.toString()).get();
}
catch(Exception e) { e.printStackTrace(); }
}
Activity is a private field that is passed to the adapter in the constructor of the adapter:
public GameHistoryAdapter(Activity a, int selectedIndex) {
this.activity = a;
}
The FileDownloader class contains an OnPreExecute method where I want to show the progress dialog on the activity:
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new ProgressDialog(activity);
dialog.setMessage("Downloading...");
dialog.setIndeterminate(true);
dialog.setCancelable(true);
dialog.show();
}
But whatever I try, the dialog does not appear. When I create an alert dialog in the OnPostExecute method of the AsyncTask, the dialog will show.
#Override
protected void onPostExecute(String res)
{
super.onPostExecute(res);
dialog.hide();
new AlertDialog.Builder(activity)
.setTitle(activity.getString(R.string.save_pdf_title_text))
.setMessage(activity.getString(R.string.save_pdf_text) + PDFFileName)
.setPositiveButton(activity.getString(R.string.close_text), null)
.setIcon(android.R.drawable.ic_dialog_info)
.show();
}
Does anyone know why the dialog is not appearing on my activity?
Does anyone know why the dialog is not appearing on my activity?
Yes, the following line of code...
String filepath = fd.execute("http://myurl.com/img.png", PDFFileName, GameHistoryAdapter.this.gameInfo.toString()).get();
Don't EVER use the get() method of AsyncTask. It will block the main / UI thread and makes the whole point of an AsyncTask redundant. In other words get() turns it into a synchronous process instead of an asynchronous one.
The fact you can show a dialog in onPostExecute(...) is simply because it will be called after the blocking call to get() has returned. This means the main / UI thread will no longer be frozen (blocked) and UI updates can be made once again.
Remove get() from your call to execute(...) and instead just use...
fd.execute("http://myurl.com/img.png", PDFFileName, GameHistoryAdapter.this.gameInfo.toString());
...then in your onPostExecute(...) method set you filepath variable to what it should be.
I don't know who added the get() method to AsyncTask but if I ever find them I'll have some serious words to say. It has little or no use and causes a lot of people a lot of confusion.
I have an activity named BuildingActivity that extends ListActivity.
In the onCreate() method, i'm running 7 database queries in a background thread. In that background thread, I am building an ArrayList<String> object from the data returned from the queries.
Now, I want to return that ArrayList<String> object back to my BuildingActivity thread.
Here's part of the code that Im working on:
public class BuildingActivity extends ListActivity {
private ProgressBar mProgressBar;
public ArrayList<String> buildings;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_building);
new Thread(new Runnable() {
#Override
public void run() {
ArrayList<String> list;
DataSource dbSource = new DataSource(getApplicationContext());
dbSource.open();
list = dbSource.getBuildingsList();
dbSource.close();
//*** NOW HOW DO I PASS list BACK TO onCreate()?
//*** I WANT TO MAKE buildings = list.
}
}).start();
if(!buildings.isEmpty()) {
// do Something.
// If i do buildings = list in the background thread,
// This will always be executed because the background thread can take
// some time to return the data. How do i make sure this part of
// code is executed only after the data has been returned?
}
}
}
My objective after this is to create a list from this returned list of buildings. And on clicking a building, another activity shall open. How do I get about this problem?
Thanks!
How do i make sure this part of code is executed only after the data
has been returned?
Instead of using Thread for doing task in background use AsyncTask which provide doInBackground for performing operation in background and onPostExecute methods run on UI Thread after completing background task
here use this
public void myMethod(){
Thread background = new Thread(new Runnable(){
#Override
public void run(){
Looper.prepare();
//Do your data rerieval work here
Runnable r=new Runnable() {
#Override
public void run() {
//return your list from here
}
};
handler.post(r);
Looper.loop();
}
});
background.start();
}
I've got an activity that keeps reading words to the user, and using onUtteranceCompleted with textTospeech to display something when the code is completed.
Inside onUtteranceCompleted I have this code to delay a function with a second:
Runnable task = new Runnable() {
public void run() {
//runs on ui
runOnUiThread(new Runnable() {
public void run() {
readWord();
}
});
}
};
worker.schedule(task, 1, TimeUnit.SECONDS);
This seems like it works well, but I think it is causing a problem.
When I rotate the screen of my phone (I guess this starts a new activity).
I hear some words being read in the background. I guess this is because of runOnUiThread() which makes the activity continue in the background.
How could I avoid 2 activities running ? I would prefer if I don't have to stop the screen from rotating on doing some weird patch!
Thank you
EDIT:
public void readWord() {
if (this.readingOnPause) {
return;
}
txtCurrentWord.setText(currentItem[1]);
this.hashAudio.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,"word");
this.tts.setLanguage(Locale.US);
this.tts.speak(this.currentItem[1], TextToSpeech.QUEUE_FLUSH,this.hashAudio);
}
EDIT2:
instantiation of worker:
private static final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor();
I would use a Handler instead of runOnUiThread().
For one thing, you're using a Thread that starts another Thread - why?
Secondly, if you create a simple Handler, it should kill itself on the rotate config change. IE:
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
// do your background or UI stuff
}
};
Then later use a Thread to call the handler, which will kick off whatever process you want to run on the UI thread:
new Thread() {
#Override
public void run() {
long timestamp = System.currentTimeMillis();
// thread blocks for your 1 second delay
while (System.currentTimeMillis() - timestamp <= 1000) {
// loop
}
handler.sendEmptyMessage(0);
}
}.start();
Ok so this is a fix I've come up with, if someone has a better solution, I'm listening.
I've added android:configChanges="keyboardHidden|orientation" inside the activity in the androidmanifest
2.
and then a function that is called when the screen is rotate:
#Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
setContentView(R.layout.streaming);
initializeUI(); //contains all the findViewByID etc...
}
I have a long running method that is called during onCreate, this method populates textviews so interacts with the UI, and updates maybe 70 labels (about 3-20 seconds depending on device).
I want to display a progressdialog as this method executes.
Ideally I want to fire my method on the UI thread once the Activity has been displayed and the progress is displayed, this I cannot do, the Activity won't paint until the method has finished.
I hoped to find an event which was fired after the activity was displayed, and I found the one below, but it still leaves the screen black until the method has finished.
#Override
public void onPostCreate(Bundle savedInstanceState)
I am normally a WP7 developer, and in .NET you add an event handler for onLoadComplete which is fired after the ui is displayed, but before the user has a chance to interact withthe UI, how do I do this in Android JAVA?
Thanks
Put a ProgressBar in the View.
Then in the onCreate() or onResume() method do this:
new Thread() {
public void run() {
yourLargeMethod();
}
}.start();
Now you can do this inside your method to update the progressBar
public void yourLargeMethod() {
// doSomething
...
runOnUiThread(new Runnable() {
public void run() {
// update the progress from the thread
progressBar.setProgress(x); // x is your progress, 0 <= x <= progressBar.getMax()
}
});
}