How can i create/bind a service only after activity layout is rendered?
-- Update
I have two tabs (both as separate activities)on the main activity and the data used for tabs comes from Service. Right now i'm binding service inside onCreate method. Issue is that layout is not rendered till all the statements inside the onCreate gets finished. A blank screen is shown till the service get bind
See ViewTreeObserver
More info here: https://stackoverflow.com/a/7735122/338479
Put the call to create/bind the service at the end of your onCreate activity. If it must absolutely bind/create at the very end of the process, you can add a boolean flag to your activity indicating whether you are already bound or have already created the service. You could then override onResume() as follows:
#Override
public void onResume() {
super.onResume();
if (!flag) {
// Call code to bind/create the service.
}
}
Related
In my current application the onResume function is triggered when I load an Activity for the first time . I looked into the Activity Lifecycle, but I didn't find a way to prevent this from happening.
Can I prevent the onResume() function from loading when an Activity is loaded for the first time, without using SharedPreferences?
Firstly, as RvdK says, you should not modify the Android Activity lifecycle, you probably have to re-design your activity behavior in order to be compliant with it.
Anyway, this is the best way that I see:
1.Create a boolean variable inside your Activity
public class MyActivity extends Activity{
boolean shouldExecuteOnResume;
// The rest of the code from here..
}
2.Set it as false inside your onCreate:
public void onCreate(){
shouldExecuteOnResume = false
}
3.Then in your onResume:
public void onResume(){
if(shouldExecuteOnResume){
// Your onResume Code Here
} else{
shouldExecuteOnResume = true;
}
}
In this way your onResume will not be executed the first time (shouldExecuteOnResume is false) but it will be instead executed all the other times that the activity is loaded (because shouldExecuteOnResume will be true).
If the activity is then killed (by the user or the system) the next time it will be loaded the onCreate method will be called again so onResume will not be executed, etc..
I'm developing an Android 3.1 application.
I want to execute an AsyncTask after activity is shown. I want to show something to user before execute AsyncTask.
I've read that it is not recommend to execute AsyncTask on onCreate().
Where I have to execute AsyncTask on onStart() or onResume()?
I want to left enough time to show activity before execute it.
onCreate(), onStart() and onResume() are lifecycle methods called by the operating system and shouldn't be called directly. You can however override them to have your code executed at these stages of the activities lifecycle:
However, if you want your AsyncTask to start after all of your Views have been inflated and drawn to the screen then you need to put the code in this:
toReturn.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
public void onGlobalLayout() {
toReturn.getViewTreeObserver().removeGlobalOnLayoutListener(this);
// asyncTask.execute();
}
});
In the above example toReturn is a view in your onCreate() method. It can be any view you like.
This pulls a ViewTreeObserver from the View and add's a listener to it which will be called when the view has finished being drawn to the screen. It's important you keep the "removeGlobalOnLayoutListener()` line in as this will stop the code firing every time the View is drawn.
Answer is in onResume()
I hade same requirement in my activity where i need to show some list with other buttons and images..
List were getting data from server so used AsyncTask for that..
But before that required to show empty listview and other part of the screen..
so first when it goes to onCreate() I set empty arraylist to listview's adapter then in onResume() call the Asynctask and in that task fill the ArrayList and call adapter.notifyDataSetChanged()
Then another problem occure..when i go to next activity and come back it always call the asynctask even if i dont require..
So had put some condition like if(arrayList.size()==0) then call asynctask else dont.
You can put yur code in the onWindowsFocusChanged method. You can use a thread inside it to manage the timer to start your specific asynctask.
Be aware that this would be performed each time your activity have the focus, not only the first time you launch your activity (I don't know if this could be a problem for you).
implement a View object and override the onDraw().
that way you'll know exactly when the first screen is visible to the user
I wrote a script to simulate the user actions. The workflow is, for example, first tap an icon, launch an activity. Then do other actions.
The question is , I don't know the exact time that the activity launched completely. At present, I use sleep to make my script wait.
Is there any way to know when an activity launched completely?
I dont know what exactly you want to do when the activity started. But normally everyones requirement is to find width of a view or something to do with the UI. The thing is, onCreate is called before the UI is drawn so nothing related to the UI that involves measuring can be done here. For that we can use a global layout listener.
ViewTreeObserver vto = outerLayout.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
outerLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
//This is executed once the layout is drawn. AFAIK this is as close as it gets
to when the activity is started.
}
});
Is your final task is to run something after activity is launched... do this
First method called from activity is onCreate() , Hence we can say completing the onCreate() system calls onStart() which calls onResume() method... as onResume() completes you can say your activity is launched properly...
If you are not going to override onStart() or onResume() what I am going to describe can be written as last statements of onCreate(). That's I usually do when I don't need onStart() or onResume().
You can create an object of Handler. Like
Handler handler = new Handler();
Handler has a method postDelayed() that is called some times after the creating and launching is finished.
call it like
handler.postDelayed(runnable,timeInMilliSeconds);
after all the processes finish, application will wait for timeInMilliSecondsms to start the process defined in run method of runnable provided in postDelayed .....
Thus
If your task is to know when the launching is finished the answer is: at the end of onResume() called from your onStart() ....
If you want to perform some action use handler.PostDelayed() method and keep timeInMilliSeconds very low... [between 1 to 10].
I want to do some cleanup in a view when the activity is being destroyed. Is there any way to get a callback in the View when the activity is being destroyed? I tried using onDetachedFromWindow, but I'm not sure whether it is correct thing to do.
If you want to get a callback without having to overload the View.onDetachedFromWindow() method, you may use the View.addOnAttachStateChangeListener() method, which takes a callback listener as a single parameter.
With the understanding that onDestroy is not guaranteed to be called, you can just callback into your view in the activities onDestroy method.
Edit in response to comment:
You can get any view by giving it an id in the layout and calling findViewById. Here's an example:
Layout.xml (only showing the bare minimum)
<LinearLayout>
<com.example.superwidget.DropDownTouchEnabledListView
android:id="#+id/special_list_view" />
</LinearLayout>
MyActivity.java (again, bare minimal and assuming proper imports)
#Override
void onDestroy() {
DownTouchEnabledListView v = (DownTouchEnabledListView)findViewById(R.id.special_list_view);
v.doCallback(with, parameters);
}
Since View contains Context, I use LocalBroadcastManager for this. So far, I haven't encountered any issues.
The View is listening to destroy event filter. The Activity then just need to broadcast destroy event.
// On View `setup` function
LocalBroadcastManager.getInstance(context).registerReceiver(receiver, filter)
// On Activity
override fun onDestroy() {
super.onDestroy()
LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
}
Don't forget to unregister the event filter once the destroy event is triggered.
presenter.destroy() // Your clean-up code here
LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver)
You can find more detail about LocalBroadcastManager here:
Blog post
Android Documentation
I would like to launch an intent when any of my activity is visible, otherwise I will put it up as a notification, and will be fired by the user.
To decide this, I need to know if any of my activity is front-most, how do I that?
I don't know that there's a method to get the currently displayed activity, but you could do something combining the Activity Lifecycle and a flag.
For the flag, if you've extended the Application class, that's probably a decent place to store it. For extending the application class, the top answer to this question has info. (d).
So probably keep track of the current active activity (or a flag that the activity is visible) in onResume/onPause or onStart/onStop depending on exactly what behavior you want.
Since you have multiple activities, you'll need a centroid place for storing the flag, which is why the Application makes sense. You can get the custom Application object by casting the application context (e.g. ((MyApplication)getApplicationContext()).isMyActivityActive).
You could extend Activity as well to help keep this code clean and contained.
If you're using a service you could bind to the service in every activity in the onStart/onStop (or onResume/onPause). If bound, you're visible.
You can ask for the running tasks from ActivityManager:
ActivityManager activityManager = (ActivityManager)getContext()
.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> runningTasks = activityManager.getRunningTasks(Integer.MAX_VALUE));
From API docs:
Return a list of the tasks that are currently running, with the most
recent being first and older ones after in order.
So the first item on the list is the frontmost activity.
onResume() called && onPause() not called = visible.
Have a public static Activity currentlyVisible; in your Application subclass that will be updated by your activities (set to the instance in onResume() and nulled in onPause()). Or invent a less ugly variant of a registry.
You could use onWindowFocusChanged(boolean hasFocus) place this in a superclass of your activities to launch the intent if it has focus.
Instead of using Activity manager there is a simple trick which you can do through code. If you observe the activity cycle closely, the flow between two activities and foreground to background is as follows. Suppose A and B are two activities.
When transition from A to B: 1. onPause() of A is called 2. onResume() of B is called 3. onStop() of A is called when B is fully resumed
When app goes into background: 1. onPause() of A is called 2. onStop() of A is called
You can detect your background event by simply putting a flag in activity.
Make an abstract activity and extend it from your other activities, so that you wont have to copy paste the code for all other activities wherever you need background event.
In abstract activity create flag isAppInBackground.
In onCreate() method: isAppInBackground = false;
In onPause() method: isAppInBackground = false;
In onStop() method: isAppInBackground = true;
You just to need to check in your onResume() if isAppInBackground is true.
n after you check your flag then again set isAppInBackground = false
For transition between two activities since onSTop() of first will always called after second actvity resumes, flag will never be true and when app is in background, onStop() of activity will be called immediately after onPause and hence the flag will be true when you open the app later on.