Can anyone help me to understand synchronous and asynchronous activities in Android?
What is exactly meant by synchronous and asynchronous activity in Android?
StartActivity, StartSubActivity and StartAcivityForResult start an activity synchronously or asynchronously, or can they behave in both ways?
Please explain as I have gone through many articles but could not find any proper explaination over this.
First of all, only one activity can be running at a time on Android, so you'll never have two activities running at the same time. Use startActivity() when you want to "fire and forget", that is, you want to launch an activity but are not expecting it to return a value to your activity. In that case, the new activity will start and your activity will be paused; you might eventually regain control once the user returns to your activity.
Use startActivityForResult() when you are expecing a result from the activity you are launching. In this case, the calling activity should override onActivityResult(), which will be called when the launched activity exits and has a result to return to you (which it sets with setResult()).
In both cases, since the calling activity and the called activity are in the same task, it's "synchronous" in a certain sense (although I think using the terms "synchronous" and "asynchronous" can be confusing in this context). The calling activity won't appear on the screen until the called activity finishes.
A useful read to know more is:
* http://developer.android.com/guide/topics/fundamentals/tasks-and-back-stack.html
-
Bruno Oliveira (Android Developer Relations, Google)
Related
My application implements an action which stretch upon 3-4 activities.
the entry point to this process can be from different activities in the application. (HomeActivity, various displayActivities). I want to return to the starting activity once the last activity is finished successfully.
Is there a best practice way to do it? thankyou.
You can use a global static boolean to help you with this (in the example SomeClass.IsClosingFlow),
Plus, you should define each activity to "mark" if it's in the "flow" (flow=meaning it's part of the pack of activities that need to be closed). I recommend using this mark as an abstract method if you all your activities are extending some abstract-activity (i.e. isActivityInFlow()).
The following code demonstrates this,
It needs to be places in onResume() of each activity in the application:
// Check to see if we are in the process of closing activities
if (SomeClass.IsClosingFlow){
if (isActivityInFlow()){
this.finish();
}
else{
// If we got here, and we're not in the flow anymore
SomeClass.IsClosingFlow = false;
}
}
There's a bunch of different ways to manage this kind of application flow. One way that may work for you and is pretty easy is to just use startActivityForResult() when you call from one activity to the next. Then, when you are finally done, you just set the result and call finish(). In each activity you can then implement onActivityResult() so that it sets the result and calls finish() on itself. In this way you can chain forward a number of activities and then chain back to whoever started the chain.
If an Asynchronous thread is a thread that operates separately to the main thread and doesn't interfere with the main thread...
Does a new Activity not occupy the main thread after it has been started through startActivity(intent)?
The majority of what I have read on this says these are both asynchronous, however there are a fair few conflicting answers and the people that say this don't really give convincing arguments.
So if anyone who has this clear in their head and could explain why they are synchronous/asynchronous, I would be a very grateful man!
Cheers
EDIT: So the answer I have derived from these two good folk and some stuff online...
Bringing Activities into the mix of synchronous/asynchronous can cause a load of horse to come about. But it is still referring to the principles of...
Synchronous methods/commands must be completed before the call stack can continue.
Asynchronous methods/commands (commonly done in a thread/AsyncTask) continue in parallel allowing the main thread of execution to continue. (It can return in its own time)
The startActivity(intent) and startActivityForResult(intent) methods are Asynchronous as they are non-blocking and allow the thread of execution to continue whilst performing their corresponding task as well.
startActivity(intent) and startActivityForResult(intent) are asynchronous in the sense that these methods return immediately without starting an Activity. Actually, they schedule an Activity to start only after the lifecycle events of the current Activity is finished.
The takeaway is, if you have something, that takes some time to finish, in the onPause() method of the first activity , the new Activity will be slow to start.
When you startActivityForResult you still perform an asynchronous call. Your caller activity gets suspended and the new is started in another process (if it runs under a different user).
But when the called activity terminates setting a result, your activity is resumed and you get onActivityResult called as a callback containing the result.
I am writing an Android app (ICS) for a tablet. The user moves from Activity A to Activity B to Activity C with the touch of a button. I want to return from Activity C to Activity A after 10 seconds. Is there some way to count to 10 without locking up Activity C?
I've succeeded with an asyncTask but if I startActivity(A) in the onPostExecute() it feels like I'm violating the guideline that an asyncTask should not mess with the UI. I've tried get() but that does lock up Activity C while it's waiting for the 10 seconds to pass.
Thanks in advance!
Assuming you have any View instance in your activity, you can use View.postDelayed() to post runnable with a given delay. In this runnable you can call Activity.finish(). You should also use View.removeCallbacks() to remove your callback in onDestroy(), to avoid your callback being called after user already navigated back from your activity.
Using AsyncTask just to count some time is just an overkill (unless you want to use AsyncTask to actually do some useful, background work). The Looper and Handler classes provide everything you need to execute any code on UI thread after a given delay. The View methods mentioned above are just convenience methods exposing the Handler functionality.
Using AsyncTask works fine as you describe. From Android Documentation:
onPostExecute(Result), invoked on the UI thread after the background computation finishes.
Since it is invoked on UI thread you should be fine.
Documentation
You can use a alarm manager for that. Set it to send a broadcast 10 seconds starting from activity a and implement a base activity for activity a b and c to receive the broadcast, after receiving the broadcast just end the current activity and start activity a with a new flag. If the current instance is activity a then ignore if not start activity a. Something like that.
As for the idle part you can update the alarm manager on every action, upon entering activity etc.
The advantage of this implementation is that you dont have to go through the hassle of having to worry about context leaks, persisting timers across activities and such. and can make use of what is already there. You can also consider using a service though.
If not you can just use the shared preference store the time to time out and check or update against it for the actions.. A simpler implementation.
Good luck.
I have 2 activities. Main Activity A & Activity B
I do not want Activity A to destroy. I am starting Activity B in a new task.
public static void startActivity(Class<?> startClass) {
Intent intent = new Intent(Constants.getActivity(), startClass);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Constants.getActivity().startActivity(intent);
}`
Constants.getActivity() returns the Context on current activity
startClass is the either activity "A" or activity "B"
Thing is they create/destroy the activities and they leak. Am I doing it wrong? How can I start activity "B" from activity "A" and vice versa keep them both in background when I dont need them.
First of all, what are you trying to do? You should always separate things you want to do in the background from your UI. Think of your Activities are simply a container to show the UI, everything else can be stored and restored from persistent storage or savedinstance bundles.
It is very crucial that you understand the difference between Activity lifecycle and Service lifecycle here.
I'm going to refer to my answer from another question here:
Your app will be in the background, onResume and onPause will both be called, provided that the OS have enough memory to keep the new app and all the old apps.
If you have a long running process that you need while the user not looking at it, use a service.
If you need the user to return the app in the same state, you need to do the work in onResume and onPause to save the state information and initialize your UI again when the user comes back. If you are really worried that it can get killed (well, it shouldn't lose the bundle I think), you can store them in SharePreferences for your app.
If you want to know when the app returns from that specific share intent, use startActivityForResult
You cannot keep an activity "alive" as you said. When an activity is paused, Android system is always able to claim its memory and unload it, at any time.
But if you want to switch from A to B, then maybe A and B can be different views inside a single activity. Maybe you'll want to have a look at http://developer.android.com/reference/android/widget/ViewFlipper.html
When you use tasks, cleanup is very important. You need to cleanup all tasks in the activity. readthis
If the activity does not have a lot of crazy initialization, just use finish and onCreates. Else be aware that onResume will be called often as you switch between activity's. Cleanup will be crucial here. If you dont cleanup, its possible one of your activities (with dead object reference from the other cleaned up activity) may come back up from the activity stack and throw exceptions. Its very difficult to debug this kinda exception.
I'm trying to kill 2 activities on the onclick of a button. The current activity and the previous activity. Using their pids. I'm just able to kill one activity. Why does this happen?
public void onClick(View v) {
android.os.Process.killProcess(pidofmain);
android.os.Process.killProcess(android.os.Process.myPid());
}
If I see in my logcat, The activity with pid "pidofmain" is getting killed whereas the current activity is not getting killed.
"pidofmain" is an integer i received from the previous activity using an intent.
Leave process killing to the OS. This is bad for any kind of program in a timesharing OS. If you want to conserve memory or something like that, let the OS handle it.
Also you can't really know if the process was correctly killed because well, if it is you wouldn't know, and if it doesn't you were not supposed to do it.
What do you want to do this for?
A much better way to do this is to call finish() for the current activity. You can also signal the previous activity to finish if it calls the current activity using startActivityForResult(Intent). The current activity would call setResult(int) before calling finish() to send a return code back to the previous activity. The previous activity can test the return code in onActivityResult(int, int, Intent) and also call finish() based on the result code.
Killing processes should be left to the OS. Once the activities finish, the will kill it off if it needs the resources. Otherwise it can let it around, which might help speed up a relaunch of your app if the user wants to run it again.
This isn't a definitive answer, but more like some thoughts that I have but it's too late for my to fire up Eclipse and prototype them. If it doesn't help you let me know and I'll try to look into it deeper tomorrow night.
A few thoughts (I hope they help):
1) Android apps really are single-threaded, and your main activity controls all the dispatch events (including events to what I assume to be a second thread that you created). If you kill the main activity, I'm pretty sure that your application would terminate execution immediately following your first call to android.os.Process.killProcess(pidofmain), and you'd never make it to your second call because you would have killed your entire application. Again, this is assuming by the variable name pidofmain that you are killing the main UI thread and not just an activity called main.
2) I'm a little curious also about where you got pidofmain? It sounds like you have three activities total, and in the first activity you get it's process id and send it to the second activity in an intent bundle, which also gets passed along to a third activity (which is the place where you're trying to kill this whole thing)? If that is the case, and you're trying to kill the currently running activity, the table in the documentation here leads me to believe that you can't just kill an activity that's in the resumed state using the same method. Official Android Docs for Activity You might want to try calling the finish() method for your currently running activity.
What exactly do you see in logcat? And what happens in the UI? Does the visible activity continue to run, but the other activity has been removed from the backstack?