简体   繁体   中英

Xamarin.Android using async method on background thread causes screen flash

So I'm trying to create a loading/splash screen for an app that I'm creating. Basically, if the user isn't authenticated, then they shouldn't be able to access the other parts of the app. Additionally, I'd like the app to attempt to sync the necessary database objects before it loads up the main activity.

The problem is that when I call the Authenticate() method and the InitLocalStoreAsync() methods, the screen flashes (almost like an activity reload, or like the app is doing something that I don't understand that's hiding the activity) while the methods are executing. I'd like that not to happen.

I'm very new to Android App Dev and even newer to Xamarin.

I'm using modified code that comes from the Azure Mobile Services tutorial on authentication etc.

Should I be somehow executing these methods using RunOnUiThread? If so, how do I await in conjunction with RunOnUiThread? Or should I be doing this in a completely different way?

I'm very lost. I've tried to search and find tutorials to follow, but I can't seem to find the answer. Here's the code so far:

protected override async void OnCreate (Bundle bundle)
    {
        base.OnCreate (bundle);
        SetContentView (Resource.Layout.Activity_Splash);
        // Create your application here

        try{
            CurrentPlatform.Init ();

            // Create the Mobile Service Client instance, using the provided
            // Mobile Service URL and key
            client = new MobileServiceClient (applicationURL, applicationKey);
            statusText = FindViewById<TextView> (Resource.Id.SplashStatusText);

            ThreadPool.QueueUserWorkItem(x => Initialize());

        }catch(Java.Net.MalformedURLException){
            CreateAndShowDialog (new Exception ("There was an error creating the Mobile Service. Verify the URL"), "Error");
        }catch(Exception e) {
            CreateAndShowDialog (e, "Error");
        }
    }

    private async void Initialize()
    {
        RunOnUiThread(() => statusText.Text = "Authenticating...");
        await Authenticate();

        RunOnUiThread (() => statusText.Text = "Syncing...");
        await InitLocalStoreAsync();

        MoveToMainActivity();
    }

    private async Task Authenticate()
    {
        try
        {
            user = await client.LoginAsync(this, MobileServiceAuthenticationProvider.Google);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
    }

    private async Task InitLocalStoreAsync()
    {
        // new code to initialize the SQLite store
        string path = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), localDbFilename);

        if (!File.Exists(path))
        {
            File.Create(path).Dispose();
        }

        var store = new MobileServiceSQLiteStore(path);
        store.DefineTable<ToDoItem>();

        // Uses the default conflict handler, which fails on conflict
        // To use a different conflict handler, pass a parameter to InitializeAsync. For more details, see http://go.microsoft.com/fwlink/?LinkId=521416
        await client.SyncContext.InitializeAsync(store);
    }

How do I restructure this so that I don't get any screen flashes?

If you want to run an asynchronous method you have to use the Task Factory:

RunOnUiThread(() => statusText.Text = "Loading.");
Task.Run(() => AsyncWork()).ContinueWith(result => RunOnUiThread(() => statusText.Text = "Done!"));

The screen flashes i think it could be 2 things, the app crashed and is trying to recover the last activity or your are trying to update elements on the UI thread and doing processing/work too, so it might be "stutter".

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM