在我的主要活动中,我在onCreate中调用setContentView。然后在onResume中我启动一个服务,如果它是第一次进入服务,它会创建一个警报并停止。我希望在调用setContentView时显示布局,但单步执行调试器表示它在服务返回之前不会出现。
一旦调用setContentView,它是否应该显示?
编辑
似乎在第一个应用程序(MAIN / LAUNCHER)的开头没有调用onWindowFocusChanged。 通过调试,似乎发生以下情况: - MAIN onCreate - onStart - onResume(这是服务启动的地方) SERVICE类 - onStart - 服务返回 MAIN -onResume - onWindowsFocusChanged(屏幕首次出现)
我看过的图表说,活动从onStart开始是可见的,但第一项活动似乎并非如此。有没有办法在开幕时强制屏幕进入视图?
答案 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
之前或之后。
答案 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 )
{
...
}
希望它有所帮助!