I have a created non activity java class for doing same calculation from different activities. This class has asynctask with progress Dialog in it. In most cases calculation is not the last operation of activity and everything goes fine, but when it is my Progress Dialog goes lost.
Example:
myJavaClass doCalculations= new myJavaClass (SomeActivity.this);
doCalculations.Do(); //<------ method Do has asysctask with Progress Dialog
finish();
result:
java.lang.IllegalArgumentException: View=com.android.internal.policy.impl.PhoneWindow$DecorView{2bbf820e V.E..... R......D 0,0-1026,483} not attached to window manager
How can I wait for asynctask to finish and then finish activity?
Additional question: Is using asynctask in non activity class is a bad practice ?
If you want to keep your activity active until the AsyncTask has finished its job, you can define a callback method in the activity that gets called when the task has finished and can react appropriately:
In the Activity:
private boolean finishAfterCurrentTask = false;
public void onTaskFinished() {
if (finishAfterCurrentTask) { // set this to true when running the last task
finish();
}
}
In the AsyncTask:
protected void onPostExecute(Object result) {
progressDialog.dismiss();
activity.onTaskFinished();
}
I'm assuming that you're keeping a reference to the activity in myJavaClass. In case that you're calling the AsyncTask from a non-UI thread, you should probably run the callback (and also all methods involving the dialog) via Activity.runOnUiThread().
As for the second question - if you use an AsyncTask in a class which methods can be called from a thread other than the UI thread, it's necessary to use runOnUiThread() to perform any operations on the UI, such as changing the contents of a view or showing/hiding a dialog, beause onPreExecute() and onPostExecute() are called from the same thread as execute().
On the other hand, if you start the task inside one of the UI callbacks, which are guaranteed to run on the UI thread, you don't need to worry about that.
The AsyncTask has a onPostExecute method you can finish the activity from there
protected void onPostExecute(Long result) {
progressDialog.dismiss();
finish(); // you'll probably have to call finish() with a callback function
}
The onPostExecute method is called when the doInBackground method is finished, on that method you can finish the activity and close the progressdialog
Related
I have a loading activity which makes few requests to server and converts data.
And layout of this activity is just simple logo image and progressBar.
All my operations were made in onCreate() and according to received request from server I start different activities:
if (request == 1) { start activity A}
else { start activity B}
The problem is loading takes 2-3 sec and operations are made even before onResume(), before activity's view come to UI.
So its just blank activity which does some work.
How can I ensure that those operations are made only after activity complete its creation?
If i clearly understand you you want to start activity 0 in which onCreate function is doing internet requests and after getting feedback from it you decide to call activity A or B. Is that correct? If yes you need to do network request in backgroud so your user interface thread doesnt freez. You can use AsyncTask for example and on it's onPostExecute method decide to fire acitivty A or B
EDIT
private class YourAsyncTask extends AsyncTask<String, Long, String> {
protected Long doInBackground(String... params) {
//here is background thread work calling net API request, hard working etc... but you can't touch UserInterface thread, since we are in background
//here call your API and parse answear
String ret = flag
return flag;
}
protected void onProgressUpdate(Long... progress) {
}
protected void onPostExecute(String result) { //here you are getting your flag from doInBackground as a result parameter
// this is executed after doInBackground, fired automatically and run on User interface thread here you can for example modify layout so you can run activity A OR B
}
}
and if you have your logic in AsyncTask you can run it from onCreate for example it doesn't matter.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_layout);
new YourAsyncTask().execute();
}
So you layot will be displayed and after executed your onPostExecute will be called
You need to move that server call off the main ui thread. Use an IntentService or something similar.
What I understand from this question, you must be using AsyncTask or Service to connect to server. You put the main thread in while loop and AsyncTask or Service is doing the required operation for you. After operation is complete, it will break out of while loop and then use if/else loop and decide which activity to start next.
Something like this:
public void onCreate(Bundle savedInstanceState)
{
boolean isDone = false;
// initialization code here
// start AsyncTask
BackgroundThread.execute(params);
while(!isDone)
{
Thread.sleep(1000); // 1 sec
}
}
doInBackground()
{
// your code
isDone = true;
}
onPostExecute() is executed on main thread, not on background thread.
so I am coming across a weird problem I cant find an explaination for. I have an async task in which in its doBackground method does a wait until a certain variable is set then the "wait" is notified
private class TestAsyncTask extends AsyncTask<Void, Object, Boolean> {
#Override
protected void onPreExecute() {
Log.d("Test1");
}
#Override
protected Boolean doInBackground(Void... params) {
Log.d("Test2");
while (nextCardToPlay == null) {
wait();
}
Log.d("Test3");
}
}
Activity A:
protected void onCreate(){
a = new TestAsyncTask().execute();
}
protected void onPause(){
a.cancel()
}
So as you can see when the activity starts, the asyncTask is started. When activity is closed the asyncTask is supposed to be cancelled.
What I noticed is that if I open the activity, close it, and reopen it again then the asynctask is created and in wait mode (never cancelled). No problem. Whats confusing is that when I start the activity (while the stale asyncTask is there), then it seems a new asyncTask is started ( because the logs from OnPreExecute are called) however the doInBackground in the nextAsyncTask is not executed because the Test2 log is not showing.
Any idea why?
This behavior is not at all weird if you look at the documentation, which states the AsyncTasks run on a single background thread, i.e. sequentially. If you really want your tasks to run on parallel worker threads, then use the executeOnExecutor() method instead of a simple execute() and pass it the AsyncTask.THREAD_POOL_EXECUTOR parameter.
How to block UI thread from doing anything and just displaying a progress bar until certain condition is met.
For example I have a list initialized to null, Lets call it list. I start another thread in UI to initialize its value which is going to take around 10 seconds. How can I block UI thread displaying progress dialog until the list is initialized.
// Initially
List list = null;
// Display progress bar until certain condition is met
while(list == null){
// Display progress dialog
}
I think AsyncTask will work if we ask that AsyncTask to update the list etc, what about another thread doing it. I have tried to simplify the problem.
you need to create a public method in mainActivity, named for examble yourcallback()
instead of instantiating all the objects in the OnCreate mainActivity, you can instantiate all objects in addition to quell ic you need for the progressbar in the callback method
yourcallback()
your callback
now you need to create an extenction of AsyncTask where you declare a base method constructor
like this
privte Activity mainObj;
public TestAsyncTask(Context context, Activity mainact ) throws Exception {
mainObj=mainact
your code
}
when the task naturally terminate the class AsyncTask call onPostExecute method
protected void onPostExecute(Long result) {
mainObj.yourcallback();
}
hope this help!
In my app I am doing some intense work in AsyncTask as suggested by Android tutorials and showing a ProgressDialog in my main my activity:
dialog = ProgressDialog.show(MyActivity.this, "title", "text");
new MyTask().execute(request);
where then later in MyTask I post results back to activity:
class MyTask extends AsyncTask<Request, Void, Result> {
#Override protected Result doInBackground(Request... params) {
// do some intense work here and return result
}
#Override protected void onPostExecute(Result res) {
postResult(res);
}
}
and on result posting, in main activity I hide the dialog:
protected void postResult( Result res ) {
dialog.dismiss();
// do something more here with result...
}
So everything is working fine here, but I would like to somehow to update the progress dialog to able to show the user some real progress instead just of dummy "Please wait..." message. Can I somehow access the progress dialog from MyTask.doInBackground, where all work is done?
As I understand it is running as separate Thread, so I cannot "talk" to main activity from there and that is why I use onPostExecute to push the result back to it. But the problem is that onPostExecute is called only when all work is already done and I would like to update progress the dialog in the middle of doing something.
Any tips how to do this?
AsyncTask has method onProgressUpdate(Integer...) that you can call each iteration for example or each time a progress is done during doInBackground() by calling publishProgress().
Refer to the docs for more details
you can update from AsyncTask's method onProgressUpdate(YOUR_PROGRESS) that can be invoked from doInBackground method by calling publishProgress(YOUR_PROGRESS)
the data type of YOUR_PROGRESS can be defined from AsyncTask<Int, YOUR_PROGRESS_DATA_TYPE, Long>
I have a problem with progress dialog on opening an activity (called activity 2 in example).
The activity 2 has a lot of code to execute in this OnCreate event.
final ProgressDialog myProgressDialog = ProgressDialog.show(MyApp.this,getString(R.string.lstAppWait), getString(R.string.lstAppLoading), true);
new Thread() {
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
showApps();
}
});
myProgressDialog.dismiss();
}
}.start();
The showApps function launch activity 2.
If I execute this code on my button click event on activity 1, I see the progress, but she doesn't move and afeter I have a black screen during 2 or 3 seconds the time for android to show the activity.
If I execute this code in the OnCreate of Activity2 and if I replace the showApps by the code on OnCreate, Activity1 freeze 2 seconds, I don't see the progress dialog, and freeze again 2 seconds on activity 2 before seeing the result.
I had the same issue and using an AsyncTask is working for me.
There are 3 important methods to override in AsyncTask.
doInBackground : this is where the meat of your background
processing will occur.
onPreExecute : show your ProgressDialog here ( showDialog )
onPostExecute : hide your ProgressDialog here ( removeDialog or dismissDialog
)
If you make your AsyncTask subclass as an inner class of your activity, then you can call the framework methods showDialog, dismissDialog, and removeDialog from within your AsyncActivity.
Here's a sample implementation of AsyncTask:
class LoginProgressTask extends AsyncTask<String, Integer, Boolean> {
#Override
protected Boolean doInBackground(String... params) {
try {
Thread.sleep(4000); // Do your real work here
} catch (InterruptedException e) {
e.printStackTrace();
}
return Boolean.TRUE; // Return your real result here
}
#Override
protected void onPreExecute() {
showDialog(AUTHORIZING_DIALOG);
}
#Override
protected void onPostExecute(Boolean result) {
// result is the value returned from doInBackground
removeDialog(AUTHORIZING_DIALOG);
Intent i = new Intent(HelloAndroid.this, LandingActivity.class);
startActivity(i);
}
}
AFAIK you cannot preload any activity with progress dialog displayed. Are you testing on a real device or in emulator?
I've seen workarounds that opened an activity with a ViewFlipper having a progress animation in the center, and in the next View, it was loaded an activity, but it's not something is recommended and hard to implement to work as you wish.
GeeXor
I would suggest you to avoid performing lots of operations in Activity 2's OnCreate.Writing lots of operations in OnCreate is a reason for the black screen between activities.So perform those operations asynchronously using AsyncTask or in a Thread (or write them in onStart if they are unavoidable).
The other suggestion is to start another progressDialog in activity 2's onCreate which will run until all of your data is loaded & user will know that something is happening in background.
this is what i would do. create a handler on the ui thread, start the background processing thread and then show the progressdialog. when the background thread has finished it's work get it to post a runnable on the ui thread via the handler to dismiss the dialog.