ProgressBar setProgress() not working after Activity recreate() - android

I have a horizontal ProgressBar which is displaying the remaining life in a game. When the life is 0 (ProgressBar progress is 0) the game ends and there is a button RESTART which calls to activity.recreate();. The progress must be shown full again when recreating but it's being shown empty (progress 0).
All is working fine and being recreated correctly but the ProgressBar. The onCreate() method has this lines:
lifeProgressBar = findViewById(R.id.lifeProgressBar);
lifeProgressBar.setMax(4);
lifeProgressBar.setProgress(4);
When recreating the activity, those lines are being called again. Even putting a breakpoint I can see that the progress is 4, but the ProgressBar is being displayed empty, the same as before recreating the activity.
I tried with invalidate, postinvalidate, etc... not worked.
How to solve this?

From recreate documentation:
public void recreate ()
Cause this Activity to be recreated with a new instance. This results
in essentially the same flow as when the Activity is created due to a
configuration change -- the current instance will go through its
lifecycle to onDestroy() and a new instance then created after it.
Here are activity life cycle when activity got recreated:
onSaveInstanceState() // Save current progress of life progress bar (0 in your case)
onDestroy()
onCreate() // You fill full life progress bar
onRestoreInstanceState() // [IMPORTANT] Activity restores previous state and set progress of life progress bar to 0.
This is expected behavior of Android, if you need to fill full life progress bar after activity got recreated, then you need to do it in onRestoreInstanceState().
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lifeProgressBar = findViewById(R.id.lifeProgressBar);
fillFullLifeProgressBar();
}
private void fillFullLifeProgressBar() {
lifeProgressBar.setMax(4);
lifeProgressBar.setProgress(4);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// Fill full life progress bar here.
fillFullLifeProgressBar();
}

Recreating your activity like this will work for you.
finish();
startActivity(getIntent());
overridePendingTransition(0, 0);

Related

which Operation will perform first in onStart or onCreate in Android

I want to perform one data base Operation once. I want to do this when My Activity is Visible. Where shall I puty my LoadDatabase() function
LoadDatabase();
this is my oncreate of activity
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.retrospectscan);
}
this is my onStart
#Override
protected void onStart()
{
super.onStart();
}
Where Shall I put my LoadDatabase Code ? So that It will operated only if activity is fully Visible.
If Any other Approach is there please help me.
The complete activity lifecycle is here:
Though loading from database may be lengthy task , you can try doing it in AsyncTask or in onStart.
You can also use it on onResume. This depends on your application use.
user2737044
use Application context and load your database in application context create().
2nd thing is that, In activity onCreate() call first then it will call onstart().

onCreate being called on Activity A in up navigation

So I have an Activity A and an Activity B. I want Activity A to be able to navigate to Activity B with the press of a button. That works, but when I use the up navigation(the home button in the action bar) to navigate back to Activity A, onCreate() is called again and the old information that the user typed in is lost.
I've seen: onCreate always called if navigating back with intent, but they used Fragments, and I'm hoping not to have to redesign the entire app to use fragments. Is there any way I can stop onCreate() from being called every time Activity A becomes active again?
This behavior is totally fine and wanted.
The system might decide to stop Activities which are in background to free some memory.
The same thing happens, when e.g. rotating the device.
Normally you save your instance state (like entered text and stuff) to a bundle and fetch these values from the bundle when the Activity is recreated.
Here is some standard code I use:
private EditText mSomeUserInput;
private int mSomeExampleField;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// TODO inflate layout and stuff
mSomeUserInput = (EditText) findViewById(R.id.some_view_id);
if (savedInstanceState == null) {
// TODO instanciate default values
mSomeExampleField = 42;
} else {
// TODO read instance state from savedInstanceState
// and set values to views and private fields
mSomeUserInput.setText(savedInstanceState.getString("mSomeUserInput"));
mSomeExampleField = savedInstanceState.getInt("mSomeExampleField");
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// TODO save your instance to outState
outState.putString("mSomeUserInput", mSomeUserInput.getText().toString());
outState.putInt("mSomeExampleField", mSomeExampleField);
}
You can make the up button behave like pressing back, by overriding onSupportNavigateUp()
#Override
public boolean onSupportNavigateUp() {
onBackPressed();
return true;
}
If you want to navigate from child to parent without recreating the parent (calling onCreate method), you may set the android:launchMode="singleTop" attribute for the parent activity in your AndroidManifest.xml

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>

show Progress Dialog within a CursorLoader in a fragment android

Good day, as the title say, anyone know how to implement a progress dialog while loading data from a CursorLoader within a fragment. can't find any example in this regard. Any link or guide on how to do it will be highly appreciated. Thank you
I think #Michal's solution would be good for showing an indeterminate ProgressDialog via ProgressDialog#setIndeterminate(true) so I've added a +1. I'm not sure adding a Fragment to a Fragment like this (SomeFragment adding DialogFragment..) is approved as I've come a cropper on SO before suggesting something similar. Plus, it's ok that the ProgressDialog is used here since ultimately it is a component of the fragment thus belongs under the fragment without needing to exist as a separate Fragment entity.
To expand on this answer, if you were wanting to provide a real-time progress update then I would suggest that after each "unit of work" (the lowest denominator of work you can count at the CursorLoader level) you should fire an event via the LocalBroadcastManger (keep it local, no one else needs to know) which your Fragment will be listening for.
On receiving the event under the Fragment's nested BroadcastReceiver#onReceive() method can get a reference to your Fragment's ProgressDialog and increment the displayed progress with incrementProgressBy(diff) or similar.
If however, you just want to pop-up a "I'm doing something" dialog then setting the ProgressDialog to use setIndeterminate(true) will suffice.
Finally, have you considered using the pattern of adding the indeterminate progress dialog to the ActionBar? That is how a lot of the core apps operate whilst an underlying CursorLoader is working. It would be nice to keep it consistent. Check out items pertaining to requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS).
Cheers.
Update
To achieve the last approach you need to set-up your parent activity (the bit owning the ActionBar) with code similar to (I'm just writing this from memory!);
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Note that this is requested before you have called setContentView...
getWindow().requestFeature(Window.FEATURE_PROGRESS);
setContentView(R.layout.yourLayout);
At this point you have said, "I would like that spinny progress thing in my Activity ActionBar". Now depending on your activity implementation you can choose to show the indeterminate progress bar immediately in onCreate by writing;
setProgressBarIndeterminateVisibility(true);
But this may be too simplistic if an additional action causes the CursorLoader to be started. What is important to note throughout this exercise is that the progress dialog in the ActionBar is a feature of the owning activity and not your underlying Fragment. You don't want your fragment assuming that the INDETERMINATE_PROGRESS feature has been requested since (a) it may not have and (b) it's not it's prerogative to understand such things. In other words if you find yourself writing getActivity().setProgressBarIndeterminateVisibility(true) stop and think.
I think you should leverage a more decoupled approach where the underlying Fragments says, "I have started to perform a load" so in your CursorLoader callback, onCreateLoader something like;
#Override
public Loader<Result> onCreateLoader(int id, Bundle b) {
// Fire event saying this load is starting.
final Intent loadStarted = new Intent();
loadStarted.setAction(YourFragment.LOAD_STARTED);
return new SomeCursorLoader(this.getActivity());
}
Your activity can be listening for this event and then when it receives it, sets the indeterminate progress bar visibility to true.
Similiarly, when the CursorLoader callback, onLoaderFinished is called then fire another event like;
#Override
public void onLoadFinished(Loader<Result> loader, Result data) {
// Fire event saying this load is finished.
final Intent loadFinished = new Intent();
loadFinished.setAction(YourFragment.LOAD_FINISHED);
}
Finally your activity can then sets the indeterminate progress bar visibility to false onReceivieing this event and the cursor results are shown to the user...
I think you can implement LoaderCallback in your Fragment there you can use
callback methods like onCreateLoader to show dialog, and onLoadFinished to dismiss dialog. Look at code below:
public class SomeFragment extends Fragment implements LoaderCallbacks<Result> {
private DialogFragment dialog;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//you should implement yours DialogFragment
dialog = new DialogFragment();
//Start loader
getLoaderManager().initLoader(0, null, this);
}
#Override
public Loader<Result> onCreateLoader(int id, Bundle b) {
//Show dialog
dialog.show(getFragmentManager(), "TAG");
return new SomeCursorLoader(this.getActivity());
}
#Override
public void onLoadFinished(Loader<Result> loader, Result data) {
handler.sendEmptyMessage(0);
}
#Override
public void onLoaderReset(Loader<Result> arg0) {
}
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
dialog.dismiss();
}
};
}

How to avoid data reload on android device back button

I am using android tab based application with TabGroupActivity, the application have a ListActivity "A" which drills down to a detail activity "D", on detail activity when i click device back button it navigate back to ListActivtiy "A" and relaods the data (ProgressBar shows progress on back button).
How can i avoid reloading of data on back buttuon ?
Any help would be appreciated.
Perhaps you can use onSaveInstanceState() to save what's needed to be saved and then restore your activity in onCreate()
If you look at the Activity LifeCycle :
When you go to another activity, and press back, it will call finish(). The first activity was on the onStop() method because it was no longer visible. So, when you come back to the first activity, it will call the method onStart(), and on Stop().
Try to overload this method without calling the super method (it might be a very bad idea).
You can also try to remember the position when you was (get the index of the current tab), and on the onResume() method, set the current tab to this index.
You just need an int attribute savedPosition in your listactivity.
private int savedPosition = -1;
#Override
protected void onPause() {
savedPosition = getListView().getFirstVisiblePosition();
super.onPause();
}
#Override
protected void onResume() {
super.onResume();
if(savedPosition != -1) {
getList().setSelection(savedPosition);
}
}

Categories

Resources