繁体   English   中英

如何在启动时在 iOS Xamarin Forms 应用程序中拨打 API 电话?

[英]How do I make an API Call in an iOS Xamarin Forms application on Launch?

我有一个 Xamarin Forms 应用程序,它在所有平台上都会在启动时点击 API 以查看是否可以访问特定服务器。

protected override async void OnAppearing()
        {
            base.OnAppearing();
            _model.LoginEnabled = false;
            await Device.InvokeOnMainThreadAsync(async () =>
            {
                try
                {
                    await Task.Delay(TimeSpan.FromSeconds(3));
                    var apiService = DependencyService.Get<IApiService>();
                    _model.IsOnline = await apiService.CheckIfOnline();
                    if (_model.IsOnline)
                    {
                        var downloader = DependencyService.Get<IDownloader>();
                        await downloader.AttemptToDownloadContentJson();
                    }
                    _model.LoginEnabled = true;
                } 
                catch
                {

                    _model.LoginEnabled = true;
                }
            });
        }

下面是检查 iOS 是否在线的接口实现:

public async Task<bool> CheckIfOnline()
        {
            try
            {
                var pathsProvider = DependencyService.Get<IPathsProvider>();
                var downloadUrl = pathsProvider.GetDownloadUrl();
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create($"{downloadUrl}api/about");
                request.Timeout = 5000;
                var response = (HttpWebResponse) await request.GetResponseAsync();
                return response.StatusCode == HttpStatusCode.OK;
            }
            catch
            {
                //Something went wrong
                return false;
            }
        }

_model.IsOnline 绑定到导航栏中的文本字符串,如果 api 可用,则显示“在线”。

预期结果是应用程序在 iOS 上打开,在可用时点击 API 并显示在线并下载“内容 JSON”。 实际结果是,在启动时,应用程序不会显示在线指示器,直到我导航离开并返回该页面。 然后一切都按预期进行,在线出现并下载了相关的 json。

在 Android 上一切正常。

是否有任何特定设置允许在启动时调用 https REST API? 目标是封闭网络上的服务器。

编辑:

  • 使用 _model.LoginEnabled 的 xaml。
<NavigationPage.TitleView> 
        <Grid VerticalOptions="Fill">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="5*" />
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="1*" />
            </Grid.ColumnDefinitions>
            <Label HorizontalOptions="Start" Text="Some Random Text" VerticalOptions="Center" TextColor="White" FontSize="28" Grid.Column="0"/>
            <Label HorizontalOptions="End" Text="Online" IsVisible="{Binding IsOnline}" Grid.Column="1"/>
        </Grid>
    </NavigationPage.TitleView>
  • 设置 BindingContext =.... 的行
public LoginPage()
        {
            InitializeComponent();
            _model = new LoginViewModel();
            _model.IsSyncing = false;
            BindingContext = _model;
        }
  • 声明 _model 的行。 例如 public MyModel _model { get; 放; }
private readonly LoginViewModel _model;
  • class _model 的声明行。 例如公共 class MyModel:INotifyPropertyChanged。
public class LoginViewModel : ObservableObject
  • _model 的 class 中声明 LoginEnabled 的行
        private bool _loginEnabled;
        public bool LoginEnabled
        {
            get { return _loginEnabled; }
            set { 
                    _loginEnabled= value;
                    OnPropertyChanged(nameof(LoginEnabled));
                }
        }

修复 #1:请在问题中添加五段代码:

  • xaml 使用_model.LoginEnabled
  • 设置BindingContext =...的行。
  • 声明_model的行。 例如public MyModel _model { get; set; } public MyModel _model { get; set; }
  • class _model 的声明行。 例如public class MyModel: INotifyPropertyChanged
  • _model 的 class 中声明LoginEnabled的行。

所有这些信息都涉及显示相关的 UI。
如果其中任何一个没有正确完成,可能会导致您看到的症状。

提示:当您以后提出问题时,请尝试考虑可能与症状相关的任何代码。 通常,问题出在您认为的地方。


修复#2:如果以上所有都是正确的,修复可能就像删除一个await一样简单。 (也意味着调用不同的调用方法。)更改:

await Device.InvokeOnMainThreadAsync(async () =>

到:

Device.InvokeOnMainThread(async () =>

解释: await强制OnAppearing暂停,直到Invoke...完成。

删除await排队Invoke...代码,允许OnAppearing立即返回,绘制页面,最重要的是,确保 Xamarin Forms 在 state 中,它正确响应绑定变量更改_model.LoginEnabled = true

副作用:这意味着页面将显示其“未登录”state,直到服务器响应。 因此,您可能想要添加一个“繁忙指示器”,表示“正在加载...”或“正在等待服务器...”等。


可选:确保非 UI 工作在 UI 线程中关闭:

Task.Run(async () =>
{
    try
    {
        // Can remove Task.Delay.
        ...
    } 
    catch {}
    
    Device.InvokeOnMainThread( () =>
        _model.LoginEnabled = true );
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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