我正在尝试在水平ProgressBar上方有一个TextView的小活动。我将进度条进度缓慢提升到100,然后我想要更改TextView.Text并将ProgressBar.Progress重置为0以显示我们现在正在加载其他内容。
我看到的奇怪的行为是,当我运行它时,TextView.Text实际上会像它应该的那样改变。然后抛出一个异常,指出“只有创建视图层次结构的原始线程才能触及其视图”。我不知道它为什么会改变然后抛出异常。如果我注释掉我重新分配TextView.Text的行,则ProgressBar表现正常(重置然后再次加载)。您可能希望失败,因为TextView和ProgressBar都是在同一视图层次结构中创建的。这是我的代码:
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.Departure);
LinearLayout linearLayout = FindViewById<LinearLayout>(Resource.Id.mainLinearLayout);
Button departButton = FindViewById<Button>(Resource.Id.departButton);
departButton.Click += (s, e) =>
{
TextView textView = new TextView(this);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WrapContent, LinearLayout.LayoutParams.WrapContent);
layoutParams.Gravity = GravityFlags.Center;
textView.LayoutParameters = layoutParams;
textView.Text = "Performing Pre-Departure Validation";
linearLayout.AddView(textView);
ProgressBar progressBar = new ProgressBar(this, null, Android.Resource.Attribute.ProgressBarStyleHorizontal);
progressBar.LayoutParameters = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MatchParent, LinearLayout.LayoutParams.WrapContent);
progressBar.Progress = 0;
linearLayout.AddView(progressBar);
(new Thread(() =>
{
Thread.Sleep(1000);
while (progressBar.Progress < 100)
{
Thread.Sleep(100);
progressBar.Progress += 5;
}
progressBar.Progress = 0;
textView.Text = "Retrieving Hazardous Material Information..";
Thread.Sleep(100);
while (progressBar.Progress < 100)
{
Thread.Sleep(100);
progressBar.Progress += 5;
}
})).Start() ;
};
}
的更新
我尝试实现Karandeep Atwal的建议,现在Activity在Run方法完成之前不显示TextView或ProgressBar。
我将点击事件更改为
departButton.Click += (s, e) =>
{
TextView textView = new TextView(this);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WrapContent, LinearLayout.LayoutParams.WrapContent);
layoutParams.Gravity = GravityFlags.Center;
textView.LayoutParameters = layoutParams;
textView.Text = "Performing Pre-Departure Validation";
linearLayout.AddView(textView);
ProgressBar progressBar = new ProgressBar(this, null, Android.Resource.Attribute.ProgressBarStyleHorizontal);
progressBar.LayoutParameters = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MatchParent, LinearLayout.LayoutParams.WrapContent);
progressBar.Progress = 0;
linearLayout.AddView(progressBar);
RunOnUiThread(new MyRunnable(progressBar, textView));
}
并将此Runnable添加到我的班级
internal class MyRunnable : Java.Lang.Object, Java.Lang.IRunnable
{
private ProgressBar mProgressBar = null;
private TextView mTextView = null;
public MyRunnable(ProgressBar progressBar, TextView textView)
{
mProgressBar = progressBar;
mTextView = textView;
}
public void Run()
{
Thread.Sleep(1000);
while (mProgressBar.Progress < 100)
{
Thread.Sleep(100);
mProgressBar.Progress += 5;
}
mProgressBar.Progress = 0;
mTextView.Text = "Retrieving ";
Thread.Sleep(100);
while (mProgressBar.Progress < 100)
{
Thread.Sleep(100);
mProgressBar.Progress += 5;
}
}
}
答案 0 :(得分:1)
在我的脑海中,尝试类似下面的代码。 这样,所有调用都将进行UI同步,Task.Delay将异步运行(因此不会阻止UI线程)。
departButton.Click += (s, e) =>
{
var ignore = TestAsync();
}
async Task TestAsync() {
await Task.Delay(1000);
while (progressBar.Progress < 100)
{
await Task.Delay(100);
progressBar.Progress += 5;
}
progressBar.Progress = 0;
textView.Text = "Retrieving Hazardous Material Information..";
await Task.Delay(100);
while (progressBar.Progress < 100)
{
await Task.Delay(100);
progressBar.Progress += 5;
}
}
答案 1 :(得分:0)
将你的代码放在这个ui线程中。通常,任何涉及用户界面的动作都必须在主线程或UI线程中完成,即执行onCreate()和事件处理的线程。
runOnUiThread(new Runnable() {
@Override
public void run() {
//stuff that updates ui
}
});