I have 3 pages in my application. Page A,B,C. When i click next button in A page the page will navigate to B page. In that page there will be some request and response process and Progress indicator will happen. Then when i click next the page will navigate to C page. There also some request and response process and Progress indicator process will happen. Now my problem is when i click back button from page C The page is navigate to B page. But the request response process and progress indicator process is working. Here i don't want do this process when i click back button. Now i have try like this:-
#Override
protected void onStart() {
super.onStart();
Log.v(this.getClass().toString(),"onStart");
}
Here the request and response process is not working when i click back button. But the progress indicator is loading. This progress indicator is continuously rolling. How to disable all the functions. I just want to go back. Do not do any other work. Please help me to solve this issue. Sorry For the poor English..
As you can see, you add a flag Intent.FLAG_ACTIVITY_CLEAR_TOP. This flag will clear all previous activities.
Intent.FLAG_ACTIVITY_CLEAR_TOP - If set, and the activity being launched is already running in the current task, then instead of launching a new instance of that activity, all of the other activities on top of it will be closed and this Intent will be delivered to the (now on top) old activity as a new Intent.
And also you finish the current activity, so navigating back to page B call B's onCreate method where you have those requests and process stuff. Avoid adding flag and finish() methods.
You don't want to override the onCreate() method for this usecase, why would you do that? The activity is created, and the process will run. What you want is to override the onBackPressed() method, so that you cannot exit the Activity until the process is complete.
Similarly to these: Android: Proper Way to use onBackPressed() with Toast but here you want to make a boolean that is set to false while the process is not complete, and set to true when it's done. Allow onBackPressed() to call super.onBackPressed() only when the boolean is true.
#Override
public void onBackPressed()
{
if(processesCompleted == true)
{
super.onBackPressed();
}
}
You can't disable the onCreate() method in android but you can however override it like you do with the onStart().
I suggest you take a look at the life cycles of either fragments or activities, depending on which you use.
Fragments:
http://developer.android.com/guide/components/fragments.html
Activities:
http://developer.android.com/reference/android/app/Activity.html
It is hard to understand what the problem really is without more code, but basically the code in onCreate will mostly not be called when you press the backbutton since an activity will be paused until the phone needs more resources and then destroys it. If an activity is destroyed the onCreate method will be called and there is nothing you can do to change that.
If my answer dosen't help, please provide more example code.
If all your cards have different activities, the backbutton should work perfectly. However if your activity is brought to the front, nothing will be reloaded, except the onresume. In the onresume you can perform a new loading structure or something you want to achieve.
When you don't have different activities, use the override at onBackPressed(), that will handle the backbutton.
But place some code for a better answer
You can create a new function in which you run the processes and call
it on onCreate and use a Boolean flag to make sure when you go back to
that activity and flag is checked the function is not called. Then
save the value of flag in savedPreference onPause() method and you are
done and onCreate() method load your saved preference.
Something like this
boolean flag = false;
#Override
public void onResume()
{
super.onResume();
// load savedPreferences
}
#Override
public void onPause()
{
super.onPause();
//save savedPreferences
}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if(flag == false)
{
//function call
processes();
}
}
private void processes()
{
flag = true;
// do stuff here
}
Related
Original question:
A button in my app starts an activity, which needs some time to prepare classes.
To let a user know this, I start a new loading activity that starts the actual activity.
This activity needs to be shown before the actual is started.
But all methods of the Android lifecycle seem to be called before the activity is shown to the user and if I start a new activity before the activity I'm currently in is shown, it won't be shown anymore.
I tried:
Starting the activity in another thread, but this does not work because the startActivity(...) seems to block the UI reload
Waiting a few milliseconds before starting the activity, but this seems dirty
Any help is appreciated! Please tell me if using a forward activity is not the right solution!
Answer for people who are searching:
Use this code to do something when the activity is already visible:
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
// do something
}
}
If the activity can also turn visible shortly after your code, use Androids lifecycle methods (here probably onResume()):
#Override
protected void onResume() {
super.onResume();
// do something
}
I have application and when I navigate back using Intent and startActivity(), views are null, onCreate() is called and activities are re-initialized. Why is that and how to bypass it?
I navigate back to activity like that:
#Override
public void onBackPressed() {
if (this.getClass() == XXX.class) {
Intent i = new Intent(this, YYY.class);
startActivity(i); //<-- activity restarts
return;
}
}
super.onBackPressed();
}
I use ActionbarSherlock, so I have activity with ActionBar initialization and every single activity just extends it. The way I navigate back to activity is described in this activity.
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_screen);
initUIComponents();
setListeners();
resetProgress();
}
and initUI() initializes UI.
EDIT
What I mean, how can I go back to previously created activity (not the one that is called via onBackPressed) and not recreate it? I use startActivity(), but apparently it recreates the whole thing
If you want that when you press back, you want to show the previous screen, then you don't have to do it in your code. Android Runtime internally maintains the stack, and will take care of showing the last-shown-activity when you press back. No need to handle it via onBackPressed()
However, if you want something other than this default action, that is when you should use onBackPressed(). Else, just let Android handle it.
So, in your application, if Activity 1 calls Activity 2, and user presses back, then the default action would be to show Activity 1 again. Don't override the onBackPressed() method
Edit:
For a custom flow of activities, you'll have to build the logic yourself. You need to override onRestart() in Activity 1, and onStop() in Activity 3. That way, onCreate won't be called again. By your logic, I mean, flags to keep track of which activity you're in, checking those flags, and calling the desired activity from there.
Edit 2:
This previous SO question, answers what you need:
Android Activity management , which suggests setting the flag FLAG_ACTIVITY_REORDER_TO_FRONT on the intent, and then calling startActivity()
Check out Android activity stack management using Intent flags for other stack reordering options: Stack management
I have an app that allows user to select a txt file from a list and then goes off to the internet to get the contents of that file. All works well except when the user accidentally or deliberately presses the hardware back button to go and see the list again.
Now, when the user clicks a new item from the list (a new file that is), instead of loading a the new file, the app continues off from where it was suspended.I do not want that to happen. I know this is related to the life cycle of the activity.
How do I make sure that it loads the new file rather than continuing from where it left off ?
I suppose you're loading the file in onCreate(). You should do that in onResume() instead.
Do not force Activities to close (e.g. use finish()). First, this does not guarantee the Activity will be closed, and second, this is better left to Android to decide.
Another Method to kill an activity is by calling following method.
#Override
public void onBackPressed() {
super.onBackPressed();
finish();
}
You can override the onBackPressed method in the activity and call finish() to get the desired outcome.
You just need to finish your activity in onBackPressed() method by calling activity.finish();
To destroy activity on back press, use this code.
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
//Destroys activity.
finish();
}
My end-goal is to have an application that runs a block of code when it (the application, not the activity) is opened up after being left ( back from home screen, etc... )
According to the Activity Lifecycle, this should be the onRestart() event on a per activity basis ( at least how I interpret it )
Both onRestart() and onResume() are being called whether I am returning to the Activity within the application (back button) AND when the app is called back up.
Given this diagram
I am interpreting it this way:
RED = movement between activities within the application
BLUE = moving to an activity outside the Application
Is my understanding incorrect?
EDIT (Clarifying specific use case)
I'm attempting to use onRestart() to replicate some security logic (PIN Validation) found in onCreate(), but it's being called even when I press the back button inside the application...
My observation is that its hard to tie the lifecycle events to user behavior on the device or emulator. Where your app is paused, if the device needs memory or wants to recover resources, it will terminate the activity, causing onCreate to be called. There is just too many scenarios to build an adequate state machine to tell yourself "how" or "why" your activity was terminated.
The only way I've found to manage this is to create a service to hold the application state and manually manage the state. The problem is trying to use the Activity state to manage the application state. The Activity design seems to have limitations that just make it a poor choice for achieving the goal you've stated.
That would be because when unless your are using Fragments each "screen" in your application is a new activity, when you click the back button it restarts the activity of the page before it.
If I am understanding what you want to do correctly you want to put your code on onCreate, not onRestart.
SEE COMMENT THREAD FOR ANSWER
Here is how to do this:-
Have a base activity that all your activities are derived from.
Add in to the base activity:-
int nAppState;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
nAppState = 0;
.
.
}
protected override void OnStop()
{
AppState();
base.OnStop();
}
public static int IMPORTANCE_BACKGROUND = 400;
protected override void AppState()
{
ActivityManager am = (ActivityManager)GetSystemService(Context.ActivityService);
IList<ActivityManager.RunningAppProcessInfo> list2 = am.RunningAppProcesses;
foreach (ActivityManager.RunningAppProcessInfo ti in list2)
{
if (ti.ProcessName.ToLower() == "com.mycompany.myapp")
{
nAppState = ti.Importance;
break;
}
}
}
protected override void OnRestart()
{
base.OnRestart();
if (nAppState == IMPORTANCE_BACKGROUND)
{
// Show a log in screen
RunOnUiThread(delegate { StartActivity(new Intent(this, typeof(LoginAppearActivity))); });
nAppState = 0;
}
}
Please note that this is in Mono C#, it will be the same code for Java, I'll leave it up to you to convert it!!
Yes, your assertions for red and blue are correct.
However, note the alternate pathway from onPause() and onStop(). Process being killed for memory reasons is a) out of your control and b) imperceptible to you if you only use onRestart() to detect "coming back" to the activity.
You have an option to avoid the previous activity by avoiding/removing the activity to come in Stack by setting some flag before calling the startActivity(intent):
intent.setFlags(i.getFlags() | Intent.FLAG_ACTIVITY_NO_HISTORY);
This will avoid the present activity to get called on back press. Alternatively you can also ovverride the onBackPressed() method of the current activity.
My application starts with a welcome screen Activity, but that screen has an option to skip that screen altogether in future launches.
What's the proper Android way to do this? Initially, I just automatically detected the skipWelcome preference and switched to the 2nd activity from Welcome. But this had the effect of allowing the user to hit the back button to the welcome screen we promised never to show again.
Right now, in the Welcome activity, I read the preference and call finish() on the current activity:
SharedPreferences preferences = getPreferences(MODE_PRIVATE);
boolean skipWelcome = preferences.getBoolean("skipWelcome", false);
if (skipWelcome) {
this.finish();
}
And then I implement onDestroy to move on to the next Activity:
#Override
public void onDestroy() {
super.onDestroy();
startActivity(new Intent(Welcome.this, StartFoo.class));
}
But this makes for some weird visual transitions. I'm starting to think that I need a base Activity that pops open Welcome only if proper, and then goes to StartFoo.
I can't comment on Mayra's answer or I would (not enough rep), but that's the correct approach.
Hidden in the Android documentation is this important phrase for Activity.startActivityForResult(),
"As a special case, if you call
startActivityForResult() with a
requestCode >= 0 during the initial
onCreate(Bundle
savedInstanceState)/onResume() of your
activity, then your window will not be
displayed until a result is returned
back from the started activity. This
is to avoid visible flickering when
redirecting to another activity."
Another important note is that this call does not block and execution continues, so you need to stop execution of the onCreate by returning
if (skipWelcome) {
// Create intent
// Launch intent with startActivityForResult()
return;
}
The final piece is to call finish immediately in the welcome activity's onActivityResult as Mayra says.
There are a few solutions to this.
Did you try just launching the activity and finishing? I vauguely remember that working, but I could be wrong.
More correctly, in if(skipWelcome) you can start the new activity for result, then when onActivityResult is called, immidiately finish the welcome activity.
Or, you can have your launcher activity not have a view (don't set content), and launch either the welcome activity or StartFoo.