Exception: Only the original thread that created a view hierarchy can touch its views

The code below works on Windows Phone but when running on Android I am getting the following exception : android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

        public ButtonLoggerPage()
                {
                    // Create the Button and attach Clicked handler.
                    Button button = new Button
                    {
                        Text = "Log the Click Time"
                    };

                    button.Clicked += OnButtonClicked;
                    opusClient.LoginCheckCompleted += OpenReadLogincheck;

                    this.Padding = new Thickness(5, Device.OnPlatform(20, 0, 0), 5, 0);

                    tbSyncItemLbl = new Label { };

                    // Assemble the page.
                    this.Content = new StackLayout
                    {
                        Children = { button,new ScrollView { VerticalOptions = LayoutOptions.FillAndExpand,

                        BackgroundColor = Color.Gray,
                        Content = loggerLayout}
                        }
                    };
                }

        void OnButtonClicked(object sender, EventArgs args)
            {

                        loginCheck();

            }

     public void loginCheck()
            {
                try
                {


                    client.LoginCheckAsync(username, password);
                }
                catch (Exception e)
                {

                    receiveErrors = 22;
                }
            }

    void OpenReadLogincheck(Object sender, LoginCheckCompletedEventArgs e)
    {


                if (e.Result != null)
                {
                    LoginStatus = e.Result.Value;
                    if (e.Result == 1)
                    {
                        addMessage("Login Succeeded", Direction.Download);

                    }

}
}

        public enum Direction { Upload, Download, DownloadFailed, UploadFailed };

             public void setSyncItem(string itemName, Direction dir)
                    {
                        tbSyncItemLbl.Text += itemName +" " + Environment.NewLine;


                        if (dir == Direction.Download)
                        {
                            this.tbSyncItemLbl.TextColor = Color.FromHex("B5DF26");
                        }
                        else if (dir == Direction.Upload)
                        {
                            this.tbSyncItemLbl.TextColor = Color.FromHex("527EA5");
                        }
                        else if (dir == Direction.DownloadFailed)
                        {
                           this.tbSyncItemLbl.TextColor = Color.FromHex("FF0000");
                        }
                        else if (dir == Direction.UploadFailed)
                        {
                           this.tbSyncItemLbl.TextColor = Color.FromHex("FF0000");
                        }

                        this.tbSyncItemLbl.YAlign = TextAlignment.Center;

                    }

         private void addMessage(string item, Direction dir)
                {
                          setSyncItem(item, dir);
                        loggerLayout.Children.Add(tbSyncItemLbl);                   
                }

        Label tbSyncItemLbl ;

Posts

  • Junior.4184Junior.4184 USMember ✭✭

    Thanks Jon

    This is the all exception:

    android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
    at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:4925)
    at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:950)
    at android.view.View.requestLayout(View.java:15461)
    at android.view.View.requestLayout(View.java:15461)
    at android.view.View.requestLayout(View.java:15461)
    at android.view.View.requestLayout(View.java:15461)
    at android.view.View.requestLayout(View.java:15461)
    at android.view.View.requestLayout(View.java:15461)
    at android.view.View.requestLayout(View.java:15461)
    at android.view.View.requestLayout(View.java:15461)
    at android.widget.ScrollView.requestLayout(ScrollView.java:1685)
    at android.view.View.requestLayout(View.java:15461)
    at android.widget.HorizontalScrollView.requestLayout(HorizontalScrollView.java:1687)
    at android.view.View.requestLayout(View.java:15461)
    at android.view.View.requestLayout(View.java:15461)
    at android.view.ViewGroup.addView(ViewGroup.java:3489)
    at android.view.ViewGroup.addView(ViewGroup.java:3436)
    at android.view.ViewGroup.addView(ViewGroup.java:3412)
    at dalvik.system.NativeStart.run(Native Method)
    } Android.Util.AndroidRuntimeException

  • Junior.4184Junior.4184 USMember ✭✭

    Many thanks Jon. I have changed the addMessage and it is working.

  • RonaldBaayenRonaldBaayen CAMember ✭✭

    @LuckyDay said:
    It's fairly common practice that you can only modify UI elements from the UI thread. Also, XF is not a phone OS in itself but rather just a tool that makes it easier to develop cross-platform apps (a distinction that seems to be forgotten quite a bit on this forum).

    Internally the different phone OS' will handle threading, UI updates, etc... differently so you're likely to see things happening differently on different platforms.

    There's quite a bit missing to be able to help debug your issue but what I would suggest is seeing if you can get a callstack for the offending UI update and determine where in your code the issue arises and wrapping that in Device.BeginInvokeOnMainThread(Action) to make sure any UI updates are occurring on the correct thread.

    For instance, you might change addMessage to:

    private void addMessage(string item, Direction dir)
    {
      Device.BeginInvokeOnMainThread(() =>
      {
          setSyncItem(item, dir);
          loggerLayout.Children.Add(tbSyncItemLbl);
      });
    }
    

    This worked like charm to me!! Thanks Tones!! :)

  • Thanks. It's help me.

  • BoomShankarBoomShankar USMember ✭✭

    Thanks. Can confirm this works just fine at least on Android.

  • RombersoftRombersoft UAMember

    Thanks for help! I love you

  • TugbaSahinTugbaSahin USMember ✭✭

    @LuckyDay said:
    It's fairly common practice that you can only modify UI elements from the UI thread. Also, XF is not a phone OS in itself but rather just a tool that makes it easier to develop cross-platform apps (a distinction that seems to be forgotten quite a bit on this forum).

    Internally the different phone OS' will handle threading, UI updates, etc... differently so you're likely to see things happening differently on different platforms.

    There's quite a bit missing to be able to help debug your issue but what I would suggest is seeing if you can get a callstack for the offending UI update and determine where in your code the issue arises and wrapping that in Device.BeginInvokeOnMainThread(Action) to make sure any UI updates are occurring on the correct thread.

    For instance, you might change addMessage to:

    private void addMessage(string item, Direction dir)
    {
      Device.BeginInvokeOnMainThread(() =>
      {
          setSyncItem(item, dir);
          loggerLayout.Children.Add(tbSyncItemLbl);
      });
    }
    

    Thanks

    Working B)

  • jigmothvsjigmothvs Member ✭✭

    I was getting same error in my code, In my case I am using ProgressDialog to set Image on ImageView, below code helped me to resolve this, setting image on same thread resolved me this error.

    Additional from above answers, Hope this helps too!!

    if (bitmap != null)
    RunOnUiThread(() => navImage.SetImageBitmap(bitmap));

                        RunOnUiThread(() => navImage.Click += NavImage_Click);
    
  • rogergccrogergcc Member ✭✭
    edited January 15

    @LuckyDay said:
    It's fairly common practice that you can only modify UI elements from the UI thread. Also, XF is not a phone OS in itself but rather just a tool that makes it easier to develop cross-platform apps (a distinction that seems to be forgotten quite a bit on this forum).

    Internally the different phone OS' will handle threading, UI updates, etc... differently so you're likely to see things happening differently on different platforms.

    There's quite a bit missing to be able to help debug your issue but what I would suggest is seeing if you can get a callstack for the offending UI update and determine where in your code the issue arises and wrapping that in Device.BeginInvokeOnMainThread(Action) to make sure any UI updates are occurring on the correct thread.

    For instance, you might change addMessage to:

    private void addMessage(string item, Direction dir)
    {
      Device.BeginInvokeOnMainThread(() =>
      {
          setSyncItem(item, dir);
          loggerLayout.Children.Add(tbSyncItemLbl);
      });
    }
    

    Thks i looking for this. [in my Receving notification put it inside a label in the view and do other functions with xamarin c#code] :) :)

  • pmg19pmg19 Member

    Friend Lucky Day

    Thanks for the hint! It helped me a lot!

    Device.BeginInvokeOnMainThread(() =>
    {
    //PERFECT!!
    });

  • Shiva799Shiva799 Member ✭✭

    I'm getting error in the insertpagebefore
    var root = MasterDetail.Detail.Navigation.NavigationStack[0];
    MasterDetail.Detail.Navigation.InsertPageBefore(page, root);
    Device.BeginInvokeOnMainThread(async () =>
    {
    await MasterDetail.Detail.Navigation.PopToRootAsync(false);
    });

    I'm not sure what is going wrong now?
    It worked fine previously

  • DeepakDYDeepakDY INMember ✭✭✭

    @LuckyDay said:
    It's fairly common practice that you can only modify UI elements from the UI thread. Also, XF is not a phone OS in itself but rather just a tool that makes it easier to develop cross-platform apps (a distinction that seems to be forgotten quite a bit on this forum).

    Internally the different phone OS' will handle threading, UI updates, etc... differently so you're likely to see things happening differently on different platforms.

    There's quite a bit missing to be able to help debug your issue but what I would suggest is seeing if you can get a callstack for the offending UI update and determine where in your code the issue arises and wrapping that in Device.BeginInvokeOnMainThread(Action) to make sure any UI updates are occurring on the correct thread.

    For instance, you might change addMessage to:

    private void addMessage(string item, Direction dir)
    {
      Device.BeginInvokeOnMainThread(() =>
      {
          setSyncItem(item, dir);
          loggerLayout.Children.Add(tbSyncItemLbl);
      });
    }
    

    It's working for me

Sign In or Register to comment.