Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

what determines when a view is actually displayed?

Tags:

android

In my main activity i call setContentView in the onCreate. Then in onResume I start a service, if it is the first time into the service it creates an alarm and stops. I expected the layout to appear when setContentView is called but stepping through the debugger indicates that it isnt appearing until the service returns.

Should it display as soon as setContentView is called?

Edit

It seems that onWindowFocusChanged is not called at the start of the first Application (MAIN/LAUNCHER). By debugging it seems that the following happens:- MAIN onCreate - onStart - onResume (this where the service is started SERVICE class - onStart - service returns MAIN -onResume - onWindowsFocusChanged (the screen appears for the first time)

The diagrams I have seen say the activity is visbile from onStart onwards but that does not appear to be the case with the first activity. Is there any way to force the screen into view at the opening?

like image 597
ron Avatar asked Aug 10 '11 14:08

ron


2 Answers

The content view is defined right after the call to setContentView(), so you can start using findViewById() and administrating the Views of the user interface straight from here.

BUT:

  • the view is not displayed before onResume() returns. This is actually one of the purposes of onResume(): it is called each and every time the Activity is going foreground, and thus just before its user interface is actually displayed.

  • this doesn't mean the UI is visible at that time even though it is displayed. For example it can be hidden by the lockscreen. onWindowFocusChanged(true) is called when the user interface is actually visible (when it has just gained the focus).

So the instant at which the user interface is both displayed and visible is between onResume() (which is called just before) and onWindowFocusChanged(true) (which is called right after).

like image 167
Shlublu Avatar answered Nov 07 '22 16:11

Shlublu


Use an AsyncTask and do an invalidate() with your Layout inside onPostExecute(). All UI drawing is done as soon as your return control to UI manager when you return from your code. There is no way to force a redraw without exiting your code, thats why people use AsyncTask or Handlers to do that.

My example:

// this goes inside your OnCreate don't use OnResume or you need to start
// your service each time apk resumes??  in that case put it inside
// OnStart()<-- start service   OnStop()<-- stop service

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

// do your initializing chores in here.....
setContenView(R.layout.mainlayout);
UIUpate ui = new UIUpdate();
ui.execute();

}


// define class somewhere in your code
private class UIUpdate extends AsyncTask<Void,Void,Void>{

@Override
protected Void doInBackground(Void... arg0) {
// fire your service here
StartMyService();

}

@Override
protected void onPostExecute(Void result) {

    //assuming you put your view inside a LinearLayout
    LinearLayout ll = (LinearLayout)findViewById(R.id.mylayout);
    // check that your topmost LinearLayout has an ID, top most hasn't by default
    ll.invalidate(); // program for update when this exit

    }

If you analise programming pattern I've put above, you'll see is not complicated. Whenever you need to update UI, one needs to think that flow is like this -> mycode()--Ui manager-- mycodepart2(), you need to break up your code in two chunks, returning in first one to UI manager and the continuing in chunk two.

Problem is that you don't have control on how to execute chunk two once you exit to UI manager, thats why AsyncTask works good, PreExecute() do chunk1, PostExecute() do chunk 2. Both parts execute inside UI thread, you can update anything UI in those. doInBackground() its another different kind of animal, its executed in own thread and cannot update UI.

like image 33
3 revs Avatar answered Nov 07 '22 18:11

3 revs