Yura Babiy
Yura Babiy

Reputation: 525

Android.OS.NetworkOnMainThreadException: in async/await block

I am trying to get drawable from URL, that points to an image. But problem is, that in android you shouldn't execute network tasks on the main thread. Because of it, I use async/await block, but the error still occurs all the time. Here is the code:

page.Appearing += async(sender, ev3) =>
                    {
                        if ( GetToolbar == null ) return;

                        GetToolbar.Subtitle = viewModel?.SubTitle;

                        if ( viewModel == null ) return;

                        if ( viewModel.AvatarUrl.Contains("?") && !viewModel.AvatarUrl.Contains("gravatar") )
                            viewModel.AvatarUrl = viewModel.AvatarUrl
                                .Substring(0, viewModel.AvatarUrl.IndexOf("?", StringComparison.Ordinal));

                        //var stream = Context.ContentResolver.OpenInputStream(Android.Net.Uri.Parse(viewModel.AvatarUrl));

                        await SetLogo(viewModel);
 }

private async Task SetLogo(PublicRepositoryPageViewModel viewModel)
        {
            var url = new URL(viewModel.AvatarUrl);
            var connection = url.OpenConnection();
            var stream = connection.InputStream;
            var logo = await Drawable.CreateFromStreamAsync(stream, viewModel.Title + "_avatar");
            GetToolbar.Logo = logo;
        }

Exactly it occurs on this line:

var stream = connection.InputStream;

If I use OpenInputStream instead of it, then it throws Java.IO.FileNotFoundException: No content provider: https://avatars.githubusercontent.com/u/6516107

I have checked Internet permission.

It is Xamarin.Forms Android project

ANSWER:

await Task.Run(async() => {
                            var url = new URL(viewModel.AvatarUrl);
                            var connection = url.OpenConnection();
                            var stream = connection.InputStream;
                            var logo = await Drawable.CreateFromStreamAsync(stream, viewModel.Title + "_avatar");
                            Device.BeginInvokeOnMainThread(()=>GetToolbar.Logo = logo);
                        });

Upvotes: 4

Views: 3278

Answers (1)

SushiHangover
SushiHangover

Reputation: 74134

A Task.Run will get you off the main thread and onto a thread in the default Threadpool:

await Task.Run(async() => {
  var url = new URL(viewModel.AvatarUrl);
  var connection = url.OpenConnection();
  var stream = connection.InputStream;
  var logo = await Drawable.CreateFromStreamAsync(stream, viewModel.Title + "_avatar");
  GetToolbar.Logo = logo;
});

Upvotes: 9

Related Questions