是什么决定了视图实际显示的时间?

时间:2011-08-10 14:47:08

标签: android

在我的主要活动中,我在onCreate中调用setContentView。然后在onResume中我启动一个服务,如果它是第一次进入服务,它会创建一个警报并停止。我希望在调用setContentView时显示布局,但单步执行调试器表示它在服务返回之前不会出现。

一旦调用setContentView,它是否应该显示?

编辑

似乎在第一个应用程序(MAIN / LAUNCHER)的开头没有调用onWindowFocusChanged。 通过调试,似乎发生以下情况: - MAIN onCreate - onStart - onResume(这是服务启动的地方) SERVICE类 - onStart - 服务返回 MAIN -onResume - onWindowsFocusChanged(屏幕首次出现)

我看过的图表说,活动从onStart开始是可见的,但第一项活动似乎并非如此。有没有办法在开幕时强制屏幕进入视图?

7 个答案:

答案 0 :(得分:6)

内容视图是在调用setContentView()后立即定义的,因此您可以直接从此处开始使用findViewById()并管理用户界面的View

<强> BUT

  • onResume()返回之前不显示视图。这实际上是onResume()的目的之一:每次Activity前进时都会调用它,因此就在实际显示其用户界面之前调用它。

  • 这并不意味着UI在当时可见,即使它已显示。例如,它可以被锁屏隐藏。当用户界面实际可见时(刚刚获得焦点时)调用onWindowFocusChanged(true)

因此用户界面显示且可见的时刻介于onResume()(之前调用)和onWindowFocusChanged(true)之间(后面称为)

答案 1 :(得分:4)

使用AsyncTask并使用onPostExecute()内的Layout执行invalidate()。 从代码返回时,只要将控制权返回给UI管理器,就会完成所有UI绘图。没有退出代码就无法强制重绘,这就是为什么人们使用AsyncTask或Handlers来做到这一点。

我的例子:

// 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

    }

如果你分析我上面提到的编程模式,你会发现并不复杂。无论何时需要更新UI,都需要认为流程是这样的 - &gt; mycode() - Ui manager-- mycodepart2(),你需要在两个块中分解你的代码,在第一个中返回到UI管理器,然后继续在第二个块中。

问题是,一旦退出到UI管理器,你就无法控制如何执行块二,这就是为什么AsyncTask工作正常,PreExecute()做chunk1,PostExecute()做块2.两个部分都在UI线程内部执行,你可以更新那些UI。 doInBackground()是另一种不同的动物,它在自己的线程中执行,无法更新UI。

答案 2 :(得分:2)

onCreate方法中,仅初始化活动。活动的真实展示就在onWindowFocusChanged之前的某个地方。来自文档

  

请记住,onResume不是您的活动对用户可见的最佳指标;诸如键盘锁之类的系统窗口可以在前面。使用onWindowFocusChanged(boolean)可以确定您的活动对用户可见(例如,恢复游戏)。

答案 3 :(得分:0)

您可以使用public void onAttachedToWindow ()的{​​{1}}回调。当与活动关联的主窗口已附加到窗口管理器时,将调用此回调。

当视图附加到窗口时,会调用Activity的{​​{1}}版本的View。此时它有一个Surface并将开始绘制。请注意,保证在onAttachedToWindow()之前调用此函数,但可以在第一个onDraw(Canvas)之前的任何时间调用此函数 - 包括onDraw之前或之后。

参考View.onAttachedToWindow()

答案 4 :(得分:0)

首先有一种称为活动生命周期的东西。根据此LINK,您的活动只有在onResume返回后才能查看。

所以有一个AsjoTask(LINK)作为mojo建议将帮助onResume在调用服务时返回(在一个单独的线程中)。

至于你的问题。如果你掌握了Activity Lifecyle,你就会知道发生了什么。

所以,如果您希望视图显示。然后你可以将服务调用放在AsyncTask 中,并将 setContent放在onCreate 中。

答案 5 :(得分:0)

调用onWindowFocusChanged()后立即显示布局。所以你需要在onWindowFocusChanged()之后做一些事情。这很简单。

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);

    if (!hasFocus) return;
    Handler h = new Handler();
    Runnable r = new Runnable() {
        @Override
        public void run() {
            Log.v("[Testing]", "run() called");
            //start your service here
        }
    };
    h.post(r);
}

答案 6 :(得分:0)

我不是专家,但是查看是否显示视图的最简单方法是:

  if ( view.window )
  {
    ...
  }

希望它有所帮助!