When the user clicks a button in my application, it will alter some data in the document being worked on and at that point I want the activity to rebuild its UI. I want to do it this way if possible because exactly what views need to be updated for any given change is going to be tricky to know in advance.
I tried getting the intent, calling finish() on the activity then calling StartActivity with the same intent. Using this method I can disable all the pending transitions, so it's fine except because it creates a new instance of the activity its state can't be recovered (unless I do something really dumb like save it to preferences). And this is not acceptable because the activity contains a ViewPager which using this method returns to page 0 whenever I update something.
Next I tried using Activity.Recreate(). This solves the issue around the state not being saved since it appears to be the same instance of the activity. But in this case I can't work out how to disable all the animations, so there is always a flash on screen.
Is there a way I can make an activity.recreate() call look seamless to the user? Or is there a better way? Since this is all within a viewpager, refreshing the fragment would work just as well, but this not happening from the fragment class itself, but rather many objects which each provide part of the UI.
I faced similar problem, when I invoked recreate on activity it was blinking, I ended up using below code:
// uncomment below line for blink effect :P
// recreate();
// restart activity without blinking :-)
Intent intent = new Intent(MyActivity.this, MyActivity.class);
startActivity(intent); // start same activity
finish(); // destroy older activity
overridePendingTransition(0, 0); // this is important for seamless transition
I know I am too late to answer your question but I hope that it will help other developers who are facing same problem.
Related
I have this really weird problem I can't quite wrap my head around. I have been pondering on this for hours and I have absolutely no clue why my code is behaving like this.
I have a Viewpager from which images can be deleted, in order to give the illusion of real time updating I open the same activity every time a photo is deleted so the viewpager's content will change immediately and accordingly.
For this reason I have overridden onBackPressed() to make sure that when this method is initiated the user returns to the real past activity and not the activity with the original images. I've read posts about this and tried to do things such as remove the super method and add the finish() method but nothing seems to work.
#Override
public void onBackPressed() {
//creates two instances of AccountApartementActivity
overridePendingTransition(0, 0);
add_button_view.setVisibility(View.INVISIBLE);
delete_button_view.setVisibility(View.INVISIBLE);
Intent i = new Intent(ApartementEditActivity.this, AccountAndApartementActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
i.putExtra("fromActivity", "2");
startActivity(i);
finish();
overridePendingTransition(0, 0);
}
In neither of the two activities' lifecycle methods I have overridden have I written code that tells the application to create the same activity twice, or I'm somehow overlooking it.
Weirdest thing is that this worked fine just a day ago but today I changed the data type of one of my variables inside my PagerAdapter method and ever since the onBackPressed() method has been broken.
Please let me know if I am missing something obvious, it happens a lot.
I think it is not the best practice to manipulate the activities stack this way. You could eventually run out of memory.
I don’t know how your photos are organized, maybe with a container layout like a gridview or a recyclerview?
Then you should update views with the adapter and the notifyDataSetChanged method.
Good luck !
Is there any best practices when changing activities in Android?
It seems very odd to me, just make an Intent and start another activity over and over.
If I just start another activity and finish the last one, when I have to move back, I need to load all the stuff back. But when I don't do it, does not seem to be the right thing to do in terms of memory handling.
Is it correct to save all the activities in a kind of ActivitiesPool or something like this? Or I will always have to choose between keeping them opened or reload them?
Any directions?
Thanks
It seems very odd to me, just make an Intent and start another activity over and ove
that's how it works on Android. To be more precise we (as developers) are not even allowed by the System to call new Activity() you just startActivity(intent);
I need to load all the stuff back
again, the framework is taking care of loading/unloading resources as needed
Is it correct to save all the activities in a kind of ActivitiesPool
no, it's not correct, don't touch them.
If you want the user to be able to click the back button and go to the previous activity, DO NOT call finish(); on it. You can use onPause()/onResume() callbacks to handle background operations and UI status should be saved on #Override protected void onSaveInstanceState(Bundle outState) callback. You put all the UI state that you need in there. If the system needs memory it will destroy the activity and whenever the user is going back to it, it will create it again onCreate(Bundle savedInstances) and then you'll have all the UI state saved there for you to proper re-create the state where the user was before.
That's how it works.
What to do when:
1. The app uses a complex structure of Activities and Fragments
2. I return to a backgrounded application that has been (partially or not) destroyed in the meantime
3. It returns me to the last screen, which lies deep in the workflow
4. I need it to return to the first screen to reinitialize things (because it's complex and requires user interaction)
Just to be clear:
I am asking how to deal with the existing stack(s) of Activities and Fragments upon encountering this situation.
- action to take: launch an Intent? Just finish? Do something to held substructures and then finish?
- when to perform it - immediately in both Activity.onCreate and Fragment's empty constructor? Or are Activities sufficient?
- How best to detect it: all I've come up with so far is: binding to a Service that holds the necessary data/connection, and then asking if it's been initialized. But the binding finishes AFTER onResume.
I am not asking about anything UI-related.
I am not asking for a solution that will only work for one specific application, so don't ask for code.
If you see this question as vague, here is a one-sentence version: "How to dismiss the stack and return to the first screen?"
For details (as much, at least, as are relevant), see https://stackoverflow.com/questions/14650342.
If you recognize that your application is in an inconsistent state and you need to start over, the easiest way is to relaunch your root activity like this:
Intent intent = new Intent(this, MyRootActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
This will clear all activities from the task and restart the root activity.
I would suggest doing this in onCreate() of activities.
when app is in the background and os wants to free some memory. whole PID is killed, which kills ALL activities. Docs are misleading about this behaviour. See this post
Android app out of memory issues - tried everything and still at a loss
where hackbod (Android platform developer) kind of confirms it.
When you have mulitple activities A,B,C and when your app is killed and you want to bring it back.
onCreate(not null) of most top activity will be called. Its worth noticing that when this scenario happens and you do something like
onCreate(not null){
startActivity(new intent)
finish;
two things will happen :
startActivity will launch new activity
finish will close current activity BUT it will bring back the previous activity (from killed pid) with its onCreate(not null) which simply was next activity in the activity stack.
This might cause multiple activity instances problems.
I had a similar problem some time ago, ended up with ugly hack but it worked :
to reinit whole app, I added something like
onCreate(not null){
if(launcher activity == null){
finish();
return;
in all activities.
Depending on what you want to achieve use flags as others have suggested.
Hope that gives you some hints.
If your goal is to dismiss all the activities and get back to your home/main activity then you can simply use:
Intent intent = new Intent(getApplicationContext(), Home.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
This will clear all the activities on top of home and return you to the home screen.
I am trying to figure out how, when a user lands on my activity screen, it is "reloaded" as if it were being loaded for the first time.
I don't want my user hitting the back arrow and coming back to my activity with old information.
As it is now, when a user "comes back" to my page, the database list isn't being repopulated, and information they typed into EditText fields remains there.
I want the page, everytime the user comes to it, to be like it's their first time there.
Have you ever tried using recreate() in your current activity? Try using it after your new values are populated.
Or you can just put everything that's in the onCreate() on the onResume. A bit ugly but it works.
I have to disagree with Kartik on this, as I understand, android:noHistory='true' will remove activity from application stack. So when user hits back, user will not be able to see the activity at all.
About activity not retaining its value, I would not recommend you this, as user expects that all values would be retained when back is hit, unless there is some specific requirement that you are trying to meet.
So I guess solution to your problem is, as others have suggested do your initialization on views in onResume(). But just doing this may not be sufficient, as views like EditText will by default cache the values anyways. So you might have to manually clear those in your on onResume(). Will keep looking to find any 'perfect' solution if any to this problem.
I had solving similar problem like yours and I solve it whit lunch mode.
I think the best is to take a look of this set the lunch mode in single instance and then
in you onCreate and onResume you can code to refresh you view just the way you want it.
copy requred code into onResume() from onCreate() method
I'm using a singleTask-mode activity that handles a certain type of files by specifying a intent-filters.
I need to handle each such file Intent exactly once. The problem is onNewIntent() is only called if the task is already alive, forcing me to handle the intent from onCreate() too. Unfortunately, onCreate() gets called for a whole bunch of reasons (e.g. screen rotation), and the Intent returned by getIntent() may be the same one across several onCreate()'s.
Of course, it is possible to work-around this using some ugly hack, but I was wondering what the elegant solution would be.
So far the best solution I came up with is to setIntent(new Intent(Intent.ACTION_MAIN)) every time after handling an intent. This is a similar pattern to how web servers redirect you to a GET page after a POST page to avoid redoing an operation as result of refresh.
Thanks!
I am not sure If I get your Problem, but once you call an intent and start the new activity,
immediately after call finish(); to end the activity you are leaving. This will end your last activity and will prevent from multiple activities from running at the same time.
Also if you are using screen rotation as a way to launch activities, you can always control which one's you do not want to start multiple times by setting some checks using "If and Else" Statements.
remove singleTask will solve your problem;
call remove singleTask's activity, can replace with:
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
How about setIntent(null) after handling it?