重新分配TextVIew.Text重新分配文本,然后在Xamarin Android

时间:2016-06-22 17:48:15

标签: android xamarin textview

我正在尝试在水平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;
            }
        }
    }

2 个答案:

答案 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

}
});