使用 setContentView 加载布局时显示 ProgressDialog
这是我的场景:我有一个登录屏幕,可以打开另一个活动。在 Activity 中,我只是有:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_details);
}
布局有点重,因为它由一些片段组成,加载大约需要 1.5 秒。 现在,当 setContentView
完成布局膨胀时,如何显示 ProgressDialog
?我尝试过通过将 setContentView
放入 doInBackground
中来使用 AsyncTask
,但当然这是不可能的,因为 UI 可以从仅 UI 线程。 因此,我需要在 UI 线程中调用 setContentView
,但是我必须在哪里显示/关闭 ProgressDialog
?
我很感激你的帮助。
弗拉。
编辑:我遵循了@JohnBoker之前的建议,这是我现在的代码:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_empty_layout);
new ContentSetterTask().execute("");
}
private class ContentSetterTask extends AsyncTask<String, Void, Void> {
public ProgressDialog prgDlg;
@Override
protected void onPreExecute() {
android.os.Debug.waitForDebugger();
prgDlg = ProgressDialog.show(MultiPaneActivity.this, "", "Loading...", true);
}
@Override
protected Void doInBackground(String... args) {
android.os.Debug.waitForDebugger();
ViewGroup rootView = (ViewGroup)findViewById(R.id.emptyLayout);
LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View inflated = inflater.inflate(R.layout.activity_details, rootView);
return null;
}
@Override
protected void onPostExecute(Void arg) {
android.os.Debug.waitForDebugger();
if (prgDlg.isShowing())
prgDlg.dismiss();
}
}
}
该行
View inflated = inflater.inflate(R.layout.activity_details, rootView);
给了我错误:
06-27 16:47:24.010:
ERROR/AndroidRuntime(8830): Caused by:android.view.ViewRoot$CalledFromWrongThreadException:
Only the original thread that created a view hierarchy can touch its views.
this is my scenario: I've got a login screen that opens another activity. In the Activity I simply have:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_details);
}
The layout is kind of heavy, cause it is made of some fragments, and takes about 1.5 seconds to load.
Now, how can I display a ProgressDialog
while setContentView
finishes inflating the layout? I've tried with AsyncTask
by putting the setContentView
in the doInBackground
, but of course that cannot be done, as the UI can be updated from the UI thread only.
So I need to call setContentView
in the UI thread, but where do I have to show/dismiss the ProgressDialog
?
I appreciate your help.
Fra.
EDIT: I followed @JohnBoker's previous suggestion, this is the code I have now:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_empty_layout);
new ContentSetterTask().execute("");
}
private class ContentSetterTask extends AsyncTask<String, Void, Void> {
public ProgressDialog prgDlg;
@Override
protected void onPreExecute() {
android.os.Debug.waitForDebugger();
prgDlg = ProgressDialog.show(MultiPaneActivity.this, "", "Loading...", true);
}
@Override
protected Void doInBackground(String... args) {
android.os.Debug.waitForDebugger();
ViewGroup rootView = (ViewGroup)findViewById(R.id.emptyLayout);
LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View inflated = inflater.inflate(R.layout.activity_details, rootView);
return null;
}
@Override
protected void onPostExecute(Void arg) {
android.os.Debug.waitForDebugger();
if (prgDlg.isShowing())
prgDlg.dismiss();
}
}
}
The row
View inflated = inflater.inflate(R.layout.activity_details, rootView);
gives me the error:
06-27 16:47:24.010:
ERROR/AndroidRuntime(8830): Caused by:android.view.ViewRoot$CalledFromWrongThreadException:
Only the original thread that created a view hierarchy can touch its views.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我决定在这里为未来的读者做出完整的回答。
在这个问题上花了几个小时后,我意识到问题是我正在尝试做两件事:
需要进行的操作
UI 线程的设计。
实际上,但这并没有改变
结果),这可以从
仅 UI 线程,因为 Services
无法显示任何对话框。
因此,由于这两个调用都是从 UI 线程进行的(onCreate 或 AsyncTask 没有区别,它仍然是 UI 线程),因此第一个调用会阻止第二个调用正确显示。
底线是:目前在 Android 中这个问题无法解决。希望我们能够获得一些更好的 API 来与 UI 交互,因为我们现有的 API 有点糟糕。
我将通过更改布局并使其更轻(如果可能的话!)来解决这个问题。
谢谢大家!
I decided to make a full answer here for future readers.
After several hours spent on the issue, I realized that the issue is I'm trying to do two things:
operation that NEEDS to be made on
the UI thread by design.
actually, but this does not change
the outcome), that can be done from
the UI thread only, since Services
can't show any Dialog.
So, as both calls are made from the UI thread (onCreate or AsyncTask makes no difference, it's still the UI thread), the first blocks the second one from showing up appropriately.
Bottom line is: this problem can't be solved in Android right now. Let's hope we can get some better APIs for interacting with the UI, because the ones we've got kind of suck.
I'm going to solve this problem by changing the layout and making it lighter (if possible!).
Thanks everyone!
创建重型视图时我遇到了同样的问题,我所做的只是在 xml 文件中放置一个线性布局并在其上调用 setContentView,然后我在 asynctask 中创建真实视图并将视图动态添加到线性布局中。
这种方法似乎有效,我能够在此过程中放置一个进度对话框。
I had the same issue when creating a heavy view, what I did was put a linearlayout only in the xml file and called the setContentView on that, then i created the real view in the asynctask and added the view dymanically to the linearlayout.
This method seems to work and i was able to put a progress dialog up during the process.
这不是一个完美的解决方案,但到目前为止最接近我需要的解决方案:我们需要在设置进度对话框(或消息视图或其他)可见和调用 setContentView() 之间需要一些时间,以便实际显示对话框/消息。
为了实现这一点,我启动一个线程执行短暂的 sleep(),然后在 UI 线程中调用 setContentView()。
这是一个带有进度对话框的示例:
我的主要问题是睡眠(20),这是一个近似值,在所有机器上可能不够。它对我有用,但如果您没有看到进度对话框,您可能必须增加睡眠持续时间。
This is not a perfect solution, but so far the closest one to what I needed: We need some time between setting the progress dialog (or message view or whatever) visible and calling setContentView(), so that the dialog/message is actually displayed.
To achieve that, I start a Thread performing a short sleep(), then calling setContentView() in the UI thread.
Here is an example with a progress dialog:
My main issue with this is the sleep( 20 ), which is an approximation, and may not be enough on all machines. It works for me, but if you don't see the progress dialog, you probably have to increase the sleep duration.