xamarin 在App.xaml.cs构造函数中使用await时出现问题

zyfwsgd6  于 2023-04-09  发布在  其他
关注(0)|答案(3)|浏览(145)

Xamarin.Forms项目中,我想根据Firestore数据库中某个文档的存在情况启动不同的页面。因此,我尝试在App.xaml.cs文件的构造函数中使用await
下面是我的代码:

public partial class App : Application
{
        public App()
        {
            InitializeComponent();

            new Action(async () => await firebaseExists())();

            if (firebaseDocExists == false) MainPage = new MyPage();
            else MainPage = new NavigationPage(new MainPage());
        }

        bool firebaseDocExists = false;

        private async Task DocExists()
        {
            var firebaseDoc = await CrossCloudFirestore.Current
                                                       .Instance
                                                       .Collection("myCollection")
                                                       .Document("docId")
                                                       .GetAsync();

           firebaseDocExists = firebaseDoc.Exists;
    }

}

我期待这一行:new Action(async () => await firebaseExists())();将更新firebaseDocExists变量的值,但实际上它保持为false,初始化的值永远不会改变。
如果修改我所采用的方法是否可以工作,或者我是否应该找到另一种方法在构造函数中使用await

xxhby3vn

xxhby3vn1#

您可以尝试将代码放入OnStart方法而不是构造函数中。例如:

public partial class App : Application
{
        public App()
        {
            InitializeComponent();
        }

        protected override void OnStart()
        {
            new Action(async () => await firebaseExists())();
            if(MainPage == null)
            {
               if (firebaseDocExists == false) MainPage = new MyPage();
               else MainPage = new NavigationPage(new MainPage());
            }
        }

        bool firebaseDocExists = false;

        private async Task DocExists()
        {
            var firebaseDoc = await CrossCloudFirestore.Current
                                                       .Instance
                                                       .Collection("myCollection")
                                                       .Document("docId")
                                                       .GetAsync();

           firebaseDocExists = firebaseDoc.Exists;
    }

}

更新1:

我不明白你为什么使用new Action(async () => await firebaseExists())();,但你可以尝试修改代码,比如:

public partial class App : Application
{
        public App()
        {
            InitializeComponent();
        }

        protected override async void OnStart()
        {
            bool firebaseDocExists = await DocExists();
            if(MainPage == null)
            {
               if (firebaseDocExists == false) MainPage = new MyPage();
               else MainPage = new NavigationPage(new MainPage());
            }
        }

        private async Task<bool> DocExists()
        {
            var firebaseDoc = await CrossCloudFirestore.Current
                                                       .Instance
                                                       .Collection("myCollection")
                                                       .Document("docId")
                                                       .GetAsync();

           return firebaseDoc.Exists;
    }

}

更新二:

在构造函数中将默认页设置为NavigationPage(new MainPage());,并在OnStart方法中更改它。

public partial class App : Application
{
        public App()
        {
            InitializeComponent();
            MainPage = new NavigationPage(new MainPage());
        }

        protected override async void OnStart()
        {
            bool firebaseDocExists = await DocExists();
            if (firebaseDocExists == false) MainPage = new MyPage();
        }

        private async Task<bool> DocExists()
        {
            var firebaseDoc = await CrossCloudFirestore.Current
                                                       .Instance
                                                       .Collection("myCollection")
                                                       .Document("docId")
                                                       .GetAsync();

           return firebaseDoc.Exists;
    }

}

更新三:

我发现MainThread.BeginInvokeOnMainThread可以在OnStart方法中将MainPage设置为as NavigationPage(new MainPage())。所以你也可以使用以下代码:

public partial class App : Application
{
        public App()
        {
            InitializeComponent();
        }

        protected override async void OnStart()
        {
            bool firebaseDocExists = await DocExists();
            if(MainPage == null)
            {  
               MainThread.BeginInvokeOnMainThread(()=>
               {
                  if (firebaseDocExists == false) MainPage = new MyPage();
                  else MainPage = new NavigationPage(new MainPage());
               });
            }
        }

        private async Task<bool> DocExists()
        {
            var firebaseDoc = await CrossCloudFirestore.Current
                                                       .Instance
                                                       .Collection("myCollection")
                                                       .Document("docId")
                                                       .GetAsync();

           return firebaseDoc.Exists;
    }

}

更新4:

protected override async void OnStart()
        {
            bool firebaseDocExists = await DocExists();
            if(MainPage == null)
            {
               if (firebaseDocExists == false) MainPage = new MyPage();
               else 
                  {
                     MainThread.BeginInvokeOnMainThread(()=>
                         {
                           MainPage = new NavigationPage(new MainPage());
                         });
                 }
            }
        }

更新五:

public partial class App : Application
{
        public App()
        {
            InitializeComponent();

            DocExists().Wait();

            if (firebaseDocExists == false) MainPage = new MyPage();
            else MainPage = new NavigationPage(new MainPage());
        }

        bool firebaseDocExists = false;

        private async Task DocExists()
        {
            var firebaseDoc = await CrossCloudFirestore.Current
                                                       .Instance
                                                       .Collection("myCollection")
                                                       .Document("docId")
                                                       .GetAsync();

           firebaseDocExists = firebaseDoc.Exists;
    }

}
4uqofj5v

4uqofj5v2#

我所采用的方法是否可以在修改后工作,或者我应该找到另一种方法在构造函数中使用await?
你发布的代码是一个复杂的方式说async void,这就是为什么它不工作。没有办法强迫它工作。
考虑一下:当操作系统要求你的应用程序显示一些东西时,它需要立即打开它,它不想等待你的应用程序在决定显示什么之前与某个数据库进行对话。
实际上你需要做的是添加第三个状态:“加载”状态。
一旦你这样做了,答案就简单多了:加载加载状态,然后 * 开始 * 异步工作。当异步工作完成时,然后更改为其他状态之一(或者如果DB查询失败,则更改为错误状态)。

lymgl2op

lymgl2op3#

经过多次尝试,最终成功了。代码在App.Xaml.cs文件中实现。最后,我没有使用其他页面来处理这种情况。

public partial class App : Application
{
        public App()
        {
            InitializeComponent();

            MainPage = new Page(); // If this line is omitted the app shows a blank page
                                   // no matter what I tried in the Loader method.

            Loader();
        }

        
        private async void Loader()
        {
            var firebaseDocExists = false;

            var firebaseDoc = await CrossCloudFirestore.Current
                                                       .Instance
                                                       .Collection("myCollection")
                                                       .Document("docId")
                                                       .GetAsync();

            firebaseDocExists = firebaseDoc.Exists;

            if (firebaseDocExists == false) MainPage = new MyPage();
            else MainPage = new NavigationPage(new MainPage());
        }
}

相关问题