I want to launch an activity, and show the progress of the loading of the activity as methods are completed. The methods will, for example, be downloading data. The problem is, the loading bar never actually shows as empty at the beginning, it simply loads once all methods are complete and shows 100% full.
I have tested a few implementations, but with no luck. The current state I am in is that I set the loading bar to max in onCreate, then carry out processing in onWindowFocusChanged. The issue is, that the loading bar is never drawn after onCreate. I have tested placing methods into onResume also, but again the progress bar only appears AFTER onCreate, onResume and onWindowFocusChanged have all completed. This has thrown my understanding of the activity lifecycle off a bit as I thought all visual elements should be drawn after onCreate?
My current code is as follows (note that no difference is noticed if the code in onWindowFocusChanged is placed in onResume). This code is all prototyping code in an attempt to get this to work.
public class IntermediateLoadingScreen extends AppCompatActivity {
private ProgressBar loadingBar = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_intermediate_loading_screen);
loadingBar = (ProgressBar)findViewById(R.id.intermediateLoadingBar);
loadingBar.setMax(100);
Log.d("IntermediateLoadScreen","onCreate Complete");
}
#Override
public void onResume () {
super.onResume();
Log.d("IntermediateLoadScreen","onResume");
}
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
Log.d("IntermediateLoadScreen","onWindowFocusChanged");
if(hasFocus){
AsyncCollectDeviceData asyncCollectDeviceData = new AsyncCollectDeviceData(this.getApplicationContext());
asyncCollectDeviceData.execute();
loadingBar.setProgress(15);
Log.d("IntermediateLoadScreen", "Loading");
getUserContactsFromServer();
getUserGroupsFromServer();
loadingBar.setProgress(100);
/*Intent intent = new Intent(this, nextActivity.class);
startActivity(intent);*/
}
}
public void getUserContactsFromServer(){
Log.d("IntermediateLoadScreen", "getUserContactsFromServer");
loadingBar.setProgress(35);
ContactsResponse contactsResponse = new ServerRequest().submitContactsRequest();
new UserRealmDAO().updateContacts(contactsResponse);
loadingBar.setProgress(60);
}
public void getUserGroupsFromServer(){
Log.d("IntermediateLoadScreen", "getUserGroupsFromServer");
loadingBar.setProgress(80);
GroupsResponse groupsResponse = new ServerRequest().submitGroupsRequest();
new UserRealmDAO().updateGroups(groupsResponse);
loadingBar.setProgress(95);
}
}
I understand that I shouldn't really have a loading screen in an activity of it's own, and should probably have it as part of an activity that I can make visible when required. But the same activity flow should occur, so if I can get this example working it should transfer across.
To conclude, the loading bar does not show after onCreate, the previous activity simply hangs and a complete loading bar eventually pops up. How can I have the empty loading bar drawn at the beginning and fill it as i call 'loadingBar.setProgress'?
EDIT:
These are my logs I have added to the above activity, I have moved the code shown in onWindowFocusChanged into onResume:
01-20 13:10:15.430 /IntermediateLoadScreen: onCreate Complete
01-20 13:10:15.430 /IntermediateLoadScreen: onResume
01-20 13:10:20.425 /IntermediateLoadScreen: Bar set at progress 15
01-20 13:10:26.242 /IntermediateLoadScreen: Bar set at progress 80
01-20 13:10:31.457 /IntermediateLoadScreen: Bar set at progress 100
The first (splashscreen) activity stays displayed until all these logs have printed out. I have placed a Thread.sleep before every progress bar set call, so you can see that there is a at least 5 seconds between each log. Even after doing this, my activity does not display until ALL method calls in the entire class are complete.
Problem is onWindowFocusChanged(boolean hasFocus) will be called right after activity is created. So your progress bar will have 15% at beginning.
Also all your methods may run really fast, so they will be done before user can actually see some progress
Just a suggestion here. Generally if any data is to be loaded/background process to take place, there is a new feature in Android Lollipop called SplASHsCREEN. Try using THIS Splash screen- a basic app screen where it will be shown till you load all your data and after it loads, you can show the next screen.
This gives user a good feel just after launching the app instead of displaying progress bar.
Related
I want to start an activity in the onStop() method without the activity being loaded popping up on the screen which will disturb the user, I want it to just load the activity with the onstop() method in the background so that when user return to the app later on, user could see the activity being loaded, is there any way to make this possible?
I have read so many of the answers about this matter and tried LifeCycleObserver but the intent still pop up, I want it to stay in the background until user open the app again. Thank you in advance
in your_Application class create variable:
Boolean stateOn = false;
in your onStop() set value true,
like
MyApplication.stateOn = true;
in onDestroy() make it false again, (before calling super.onDestroy())
MyApplication.stateOn = false;
and in on onResume() check it, if it was true , start another activity
if (MyApplication.stateOn) {
startActivity({intent});
}
you can crate your_AppCompatActivity class and do above code in there, to appling this config in all activities who extends your_AppCompatActivity
I have an app which uses only one activity. Inside, I load a fragment with a recyclerview.
Each item in the recyclerview is a dialog fragment. The user can change the items, therefore the recyclerview is updated when the dialog is dismissed.
The problem I'm having now is that when the app is rotated while the dialog is active, the recyclerview will not get updated after the dialog is dismissed.
My dialog gets recreated along with everything in the app when destroyed so I suspect the dismisslistener gets destroyed when recreating.
The dialog exposes a method to set the dismisslistener and then overrides the event to check if one was set.
public void setOnDismissListener(DialogInterface.OnDismissListener
onDismissListener) {
this.onDismissListener = onDismissListener;
}
#Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
if (onDismissListener != null) {
onDismissListener.onDismiss(dialog);
}
}
I then set a dismisslistener inside the onViewBindHolder of the recyclerview
editor.setOnDismissListener(dialog -> {
recycler.getAdapter().notifyDataSetChanged();
}
I'm unsure why this happens, but it seems that after changing the orientation and recreating everything, the recyclerview is never updated. I found out that the method is still called, because inside the ondismisslistener was another function that updated another view with getView().findViewById() which then crashed the app because getView returned null.
I couldn't find any other post about this here.
Does anyone know how I fix the dismisslistener or maybe any other way to wait for a dialogfragment to close?
Have you added android:configChanges="orientation|screenSize" to your activity in AndroidManifest?
Otherwise try (onRestoreInstanceState() and onSaveInstanceState()
Alright I've found out what went wrong.
When recreated, the dialog loses all his variables, just like everything else.
It could be theoretically possible to save those variables in the bundle and fetch them again on recreation, but I have not found a way to do this with an OnClickListener, since objects passed to a bundle must be serializable or parcable.
Therefore, my dialogues are now just dismissed when they do not have any variables via a check in OnCreate.
I would like to start an AlertDialogue showing a loading message and a ProgressBar icon, then on showing the dialogue I would run the heavy processing with the ProgressBar spinning, and finally cancel the dialogue when the processing is over.
I have tried putting the logic on setOnShowListener of the alert dialogue which was not carried out. Then, I have tried starting the dialogue then using a delayed handler like the following:
new Handler().postDelayed(new Runnable()
{
#Override
public void run()
{
// heavy procssing logic
// alert.dismiss();
}
}, 1000);
Though, the ProgressBar icon stopped spinning, so I assumed that my heavy processing blocked the UI. How do I achieve what I need. Thanks.
Edit: I have replaced the handler with new Thread() and everything worked properly. Would this approach cause any problems like memory leaks?
Create a new AsyncTask to do your work, this will cause any code placed in the “doInBackground()” method to be ran in a background thread, you have pre-execute and post-execute to run code on the main thread, my recommendation is create an alertDialog in the pre-execute methods and close it on the post-execute, using “publishProgress()” method In the doInBackground method to update your dialog as you need.
Otherwise instead of an alertDialog (or as well as) you can use a progressBar, simply have it in the view preciously, instantiate it as you normally would.
<ProgressBar
android:id=“+id/progressBar”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
android:centreInParent=true
android:indeterminate=true
android:visibility=gone />
ProgressBar progressBar = view.findViewById(R.id.progressBar)
Now when you want to show the progress bar use
progressBar.setVisibility(visible)
Or to hide
progressBar.setVisibility(gone)
I'm writing a very simple android app. When the user touches the surface and moves their finger around, pictures are drawn below their fingers. When their finger is raised, this stops.
I want the action bar to hide when the finger is down and reappear when it is raised.
The ActionBar is overlayed. I thought using ActionBar.hide() and .show() in my view's onTouchEvent would work fine, but I've hit some problems.
I've tried a few things. First I tried passing the ActionBar created in the Activity into the view, but this didn't work as the view has to be created before the ActionBar is "got", so I would just be passing in a null value.
I then tried to make a static ActionBar which I can call from my view, but then I get this error: "Only the original thread that created a view hierarchy can touch its views.”
Anyone know of a way around this?
Take a look at one of the examples that is part of the jfeinstein10's Sliding Menu library
In it, in the BirdActivity.java, you will see how the ActionBar is shown and hidden after 2 seconds. You will naturally have to adapt the code yourself. But this should get you started:
Excerpt of the code from Line No. 53 - 58:
imageView.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
getSupportActionBar().show();
hideActionBarDelayed(mHandler);
}
});
The hideActionBarDelayed() from Line No. 80 - 86:
private void hideActionBarDelayed(Handler handler) {
handler.postDelayed(new Runnable() {
public void run() {
getSupportActionBar().hide();
}
}, 2000);
}
UPDATE
For the lack of code, most of the problem has been assumed. It may be wrong simply for the lack of data from the OP. That being said, if sorting out the "Only the original thread that created a view hierarchy can touch its views." problem will fix it, perhaps this may do it for you:
Runnable run = new Runnable() {
#Override
public void run() {
// RUN YOUR CODE TO HIDE / SHOW THE ACTIONBAR HERE
}
}; YOUR_ACTIVITY.this.runOnUiThread(run); // REPLACE WITH getActivity().runOnUiThread(run); IF THIS IS A FRAGMENT
NOTE: In the example, the activity in question uses ActionBarSherlock and extends SherlockActivity and therefore, the use of getSupportActionBar(). If you are not using ABS, you will have to use getActionBar() instead of the former.
I have an android app that has various activities.
for example there is a home screen and an update screen.
The home screen is a list activity.
A button on the home screen brings you to the update screen that updates the database from a server. In theory when Returning to teh homescreen after an update, the list should be changed to reflect the update just done.
the code for going to the update screen is as follows:
Button synch = (Button) findViewById(R.id.synchButton);
synch.setOnClickListener(new OnClickListener() {
public void onClick(View viewParam) {
Intent intent = new Intent(HomeScreen.this, SynchScreen.class);
startActivity(intent);
}
});
and the code for returning back to the homescreen after the updates is:
main_menu.setOnClickListener(new OnClickListener() {
public void onClick(View viewParam) {
finish();
}
});
the list is compiled from an async task that runs in onStart, so my understanding is that onStart should run when I return to the homescreen, thus always displaying the most up to date version of the list.
On my Emulator I always get teh updated list, but when I run it on my phone the list is never updated, it just returns to the state of teh screen before I did the update.
any ideas?
thanks
Kevin
Check the Activity lifecycle section of the Android documentation. The code updating the view should probably be moved to onResume, since the Activity might not get killed when launching a new one.
Put the code for starting the Asynctask in onResume. Read the documentation related to activity life cycle.
#Override
public void onResume() {
super.onResume();
Apaptor.refreshListView(Vector);
}