Restart activity instead reCreate [Android] - android

I have following situations with activities A,B,C:
A->B->C->A
In this last step (C->A), I want to override onBackPressed of C, so that it restarts activity A (without recreating it). I tried code below, but onCreate() of A is still called. Which flag should I add?
public void onBackPressed() {
Intent intent=new Intent(C.this, A.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}

This is the best way to refresh your activity:
public void refresh() {
Intent intent = getIntent();
overridePendingTransition(0, 0);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
finish();
overridePendingTransition(0, 0);
startActivity(intent);
}

OnCreate will be called, this is the correct behavior, below is from Google documentation:
When your activity is recreated after it was previously destroyed, you can recover your saved state from the Bundle that the system passes your activity. Both the onCreate() and onRestoreInstanceState() callback methods receive the same Bundle that contains the instance state information.
Because the onCreate() method is called whether the system is creating a new instance of your activity or recreating a previous one, you must check whether the state Bundle is null before you attempt to read it. If it is null, then the system is creating a new instance of the activity, instead of restoring a previous one that was destroyed.
but this does not matter if you handle it properly, for instance:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // Always call the superclass first
// Check whether we're recreating a previously destroyed instance
if (savedInstanceState != null) {
// Restore value of members from saved state
mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
} else {
// Probably initialize members with default values for a new instance
}
...
}

public void onBackPressed() {
Intent intent=new Intent(C.this, A.class);
// remove below Flag and while going from A dont call finish();
//intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}

So you want to make sure, that activity A is in the same state as it was before you switched to activity B, right?
Have you tried using the onSaveInstanceState() / onRestoreInstanceState() (respectively onCreate(Bundle savedInstanceState)) callbacks as described in: https://developer.android.com/training/basics/activity-lifecycle/recreating.html ?
Example here: https://stackoverflow.com/a/151940/3540885
I am not sure if your desired way is possible. Usually it is better to let Android handle the lifecycle itself. Just save the important stuff whenever the system feels like destroying your activity - so you can recreate it with the last state again...
edit:
It is long ago since I last messed around with multiple activities. Have you considered using Fragments instead of multiple activities? Once I got the concept of the Fragments, I started using only one parent Activity and replacing Fragments. So all your "heavy stuff" could be instantiated once in the parent activity and accessed by the fragments who need it. This could be an alternate solution, which is IMHO worth to think about.

I like Stanojkovic answer and to save data you can pass it using the intent.
public void refresh() {
Intent intent = getIntent();
intent.putExtra("extra_id",details);
overridePendingTransition(0, 0);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
finish();
overridePendingTransition(0, 0);
startActivity(intent);
}
and to get it in onCreate
details=getIntent().getStringExtra("extra_id")

Related

Restarting app without worrying about onSaveInstanceState

How do I simply just restart my ENTIRE app instead of trying to worry about saving the instance perfectly in onSaveInstanceState and reinitializing everything perfectly when resumed/restored in onRestoreInstanceState? (this can quickly become error prone)
UPDATE 10.1.16
I chose to do this in onCreate since onRestoreInstanceState behaves oddly sometimes.
This method is based on the fact that the onCreate(Bundle) is null unless the activity is being revived in which case it is whatever onSaveInstanceState(Bundle) set it to.
I set TWO flags. One in onSaveInstanceState in the Bundle so to know that it is a valid Bundle set by me. The other in the class itself to determine if onCreate was called because of recreation or rotation. And so in onCreate I checked to see if onSaveInstanceState is not null, check the Bundle flag, and check bInit (which defaults to false). If both flags are true then it means android dumped and destroyed our apps memory and the safest way to ensure everything is initialized again in a linear-style application is to just restart it and launch the beginning activity.
public class SomeMiddleActivity extends AppCompatActivity
{
private static boolean bInit = false; // only way it will be false again is if android cleared our memory and we are recreating
#Override
public void onSaveInstanceState(Bundle state)
{
// set a flag so that onCreate knows this is valid
state.putBoolean("StateSaved", true);
super.onSaveInstanceState(state);
}
#Override
protected void onCreate(Bundle savedInstanceState)
{
// this must be called first always for some reason
super.onCreate(savedInstanceState);
if (savedInstanceState != null)
{
if (savedInstanceState.getBoolean("StateSaved", false) && !bInit)
{
// we were recreated... start app over
Intent intent = new Intent(getApplicationContext(), Startup.class);
startActivity(intent);
finish();
return;
}
}
bInit = true; // this will stay true until android has cleared our memory
.......
}
Hope this helps someone and although this has worked thus far, if anyone has a different suggestion let me know.
And FYI: the onSaveInstanceState(Bundle, PersistableBundle) version of onSaveInstanceState is never called ever so I dont know why they even implement it. (?)
REFERENCES:
ACCORDING TO ANDROID DOCUMENTATION
onCreate
Bundle: If the activity is being re-initialized after previously being shut down then this Bundle contains the data it most recently supplied in onSaveInstanceState(Bundle). Note: Otherwise it is null.
Try implementing this way
private final String IS_RE_CREATED = "is_re_created";
#Override
public void onSaveInstanceState(Bundle outState) {
outState.putBoolean(IS_RE_CREATED, true);
super.onSaveInstanceState(outState);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
if (savedInstanceState.containsKey(IS_RE_CREATED)) {
boolean isRecreated = savedInstanceState.getBoolean(IS_RE_CREATED, false);
if (isRecreated) restartApplication(this);
}
}
public void restartApplication(Context context) {
String packageName = context.getPackageName();
PackageManager packageManager = context.getPackageManager();
// Intent to start launcher activity and closing all previous ones
Intent restartIntent = packageManager.getLaunchIntentForPackage(packageName);
restartIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
restartIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(restartIntent);
// Kill Current Process
Process.killProcess(Process.myPid());
System.exit(0);
}
Note: It is not a recommended to forcefully restart application.
How do I simply just restart my app instead of trying to worry about saving the instance
You mean the current activity? Do nothing (Don't implement onSaveInstanceState and onRestoreInstanceState).
The activity gets created automatically when changes happen. If there is no saved instance state, the activity won't restore any data.
Edit:
I think I came across similar issue too few weeks earlier, where I've to kill all the activities in the back stack and open a fresh new activity.
// Start Main Activity
Intent intent = new Intent(this, MainActivity.class);
finishAffinity();
startActivity(intent);
Use finishAffinity(). This works on > API 16.
When you kill all the activities in the back stack and open the main activity, it is kind of similar to restarting your app.

save data while destroying and recreating activity

I've settings(called from onCreateOptionMenu) from my Activity which uses to update the UI on current Activity.
Starting Preferences on updating Preferences, Calling Activity needs to update UI on Preference basis.
Snippet how Preference called:-
Intent in = new Intent(this, PrefsSecondaryActivity.class);
in.putExtra("caller", "sx");
startActivityForResult(in, SECSETTINGS);
Catch to get the UI updates
if (requestCode == SECSETTINGS) {
Intent intent = getIntent();
finish();
startActivity(intent);
}
I used to Re-Create that activity with the above snippet. Inside of onCreate() of Activity. I checked the Preference Name-value Pair and update the UI which workd perfectly fine.
How to store the values which are inside that activity while destroying and recreating activity?
As I'm Destroying and Recreating activity which renders whole new Activity with no values inside of it.
I tried to set onSavedInstanceState() while calling Preferences and onRestoreInstanceState() is called in catch the onActivityResult()
Settings values in Preferences makes good change of SLOC. So it's not preferrable way right now.
Any suggestion would be welcome.
This is how I do that (I have some static variables declared in my Activity):
#Override
protected final void onRestoreInstanceState(final Bundle inState)
{
// Restore the saved variables.
isChartShown = inState.getBoolean("chart", false);
qIndex = inState.getInt("index");
scores = inState.getIntArray("scores");
}
#Override
protected final void onSaveInstanceState(final Bundle outState)
{
// Save the variables.
outState.putBoolean("chart", isChartShown);
outState.putInt("index", qIndex);
outState.putIntArray("scores", scores);
}
This code works for me. I use it for saving some state variables used to maintain the values upon rotation.
[EDIT]
Otherwise, if you force the app finishing, then you'd go for Sharedpreferences:
just save your values before finishing and reload them in onCreate.

Find out whether the current activity will be task root eventually, after pending finishing activities have disappeared

If FirstActivity is the root of the task, and it finishes itself and launches SecondActivity, then calling isTaskRoot() in SecondActivity immediately will return false, because the FirstActivity's finishing happens asynchronously and thus isn't done yet. Waiting for a second and then calling isTaskRoot() returns true.
public class FirstActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
finish();
startActivity(new Intent(this, SecondActivity.class));
}
}
public class SecondActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
#Override
protected void onResume() {
super.onResume();
((TextView)findViewById(R.id.tv1))
.setText("isTaskRoot() in onResume(): " + isTaskRoot());
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
((TextView)findViewById(R.id.tv2))
.setText("isTaskRoot() after 1s: " + isTaskRoot());
}
}, 1000);
}
}
Is there a way to …
(optimally) find out whether the activity will be the task root eventually, or,
(better than nothing) get some sort of notification/callback once the task is in its "final" state and thus isTaskRoot() will return the "truth"?
I've had a similar problem and I wanted tight control over exactly who the root activity is. In my case, the root could only be one of my own activities (not 3rd party ones), so I was able to use the following approach:
I extended the Application class, added a weak reference to an activity called currentRootActivity and added synchronized getter and setter.
Then I managed this state by myself when activities were created / destroyed. My use case was a little special because I was looking to replace one root with another, so I knew exactly where to reset my new state variable, but I'm pretty sure you can do the same.
I was even able to add this state logic in a shared base class for all of my activities. So this wasn't as disgusting as it sounds :)
As mentioned in the comments, the activity method isFinishing might also come in handy.
Try:
Intent intent = new Intent(this, SecondActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
I expect that this will make SecondActivity the root activity.

Why do OnCreate should be called only once on the start of Activity?

I would like to know, why OnCreate() is called only once at the start of an activity?
Can we call OnCreate() more than once in the same activity?
If yes, than how can we call it? can anyone give an example?
Thanks a lot!!!
Why would you want to called it again? unless the activity is reconstructed, which is called by system. You cannot call OnCreate manually , it is the same reason why you won't call setContentView() twice. as docs:
onCreate(Bundle) is where you initialize your activity. Most
importantly, here you will usually call setContentView(int) with a
layout resource defining your UI, and using findViewById(int) to
retrieve the widgets in that UI that you need to interact with
programmatically.
Once you finish init your widgets Why would you?
UPDATE
I take some words back, you CAN do this manually but I still don't understand why would this be called. Have you tried Fragments ?
Samplecode:
public class MainActivity extends Activity implements OnClickListener {
private Button btPost;
private Bundle state;
private int counter = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
state = savedInstanceState;
btPost = (Button) findViewById(R.id.btPost);
btPost.setOnClickListener(this);
Toast.makeText(getBaseContext(), " " + counter, Toast.LENGTH_LONG)
.show();
}
#Override
public void onClick(View v) {
counter++;
this.onCreate(state);
}
}
onCreate() method performs basic application startup logic that should happen only once for the entire life of the activity .
Once the onCreate() finishes execution, the system calls the onStart() and onResume() methods in quick succession.
The initialization process consumes lot of resources and to avoid this the activity once created is never completely destroyed but remains non visible to user in background so that once it is bring back to front , reinitialization doesn't happen .
Where you want to call onCreate manually.
Then just do this.
finish();
Intent intent = new Intent(Main.this, Main.class);
startActivity(intent);
finish() calls the current stuff.
And if you are doing somethong getExtra in this activity then do this,
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putString("key",your_variable);
super.onSaveInstanceState(outState);
}
And add this to your onCreate()
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
if(savedInstanceState != null)
{
your_variable= savedInstanceState.getString("key");
}
}
Why would you want to call onCreate more than once? You will be re-creating the activity. If this is what you need for whatever reason then finish the activity and use an intent to create a new instance of that activity. Otherwise, you have two instances of the activity at the same time. Hope that helps but if that doesn't make sense then add more information as to what you want so we have context
OnCreate is basically use to create your activity (UI). If you have already created your activity then you need not create it again as you have already created.
It is basically used to initialize your activity and to create user interface of your activity. Activity is a visual part which you can use again and again so.. I think your problem is not to recreate activity but to reinitialize all components of your activity. For that purpose you can create a method initialize_act() and call it from anywhere...
#OnCreate is only for initial creation, and thus should only be called once.
If you have any processing you wish to complete multiple times you should put it elsewhere, perhaps in the #OnResume method.
Recently i realized that onCreate is called on every screen orientation change (landscape/portrait). You should be aware of this while planning your initialization process.
Recreation can be suppressed in AndroidManifest.xml:
<activity
android:configChanges="keyboardHidden|orientation"
android:name=".testActivity"
android:label="#string/app_name"></activity>

back to previous activity

I try to go to previous Activity (Activity A) but have problem. Command to this get inside Activity B and I wont to go back to B:
A:
if(...)
{
B.staticF();
}
B:
static void staticF()
{
super.onBackPressed();
}
But I can't use super because it's static context.
Of course, I can call
Intent i = new Intent(this, B.class);
startActivity(i);
but I wont to save B look.
Why not just use something like a shared preference to save the state? and then use the intent to go back and in the onCreate method get the preferences and populate any views with the data you wanted to save

Categories

Resources