如何在发布时在iOS Xamarin Forms应用程序中进行API调用



我有一个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;
}
}

_模型。IsOnline绑定到导航栏中的文本字符串;在线";如果api可用。

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

在安卓系统上一切如常。

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

编辑:

  • 使用_model的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;set;}
private readonly LoginViewModel _model;
  • 无论_model是什么类的声明行。例如,公共类MyModel:INotifyPropertyChanged
public class LoginViewModel : ObservableObject
  • _model类中声明LoginEnabled的行
private bool _loginEnabled;
public bool LoginEnabled
{
get { return _loginEnabled; }
set { 
_loginEnabled= value;
OnPropertyChanged(nameof(LoginEnabled));
}
}

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

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

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

提示:当你问未来的问题时,试着想想任何可能与症状相关的代码。通常,问题不在于你认为它在哪里


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

await Device.InvokeOnMainThreadAsync(async () =>

至:

Device.InvokeOnMainThread(async () =>

解释:await强制OnAppearing挂起,直到Invoke...完成。

删除await队列Invoke...代码,允许OnAppearing立即返回,绘制页面,最重要的是,确保Xamarin Forms处于正确响应绑定变量更改_model.LoginEnabled = true的状态。

SIDE-EFFECT:这意味着页面将显示其";未登录";状态,直到服务器响应。因此,您可能希望添加一个";繁忙指示器";上面写着";正在加载"或";正在等待服务器"等


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

Task.Run(async () =>
{
try
{
// Can remove Task.Delay.
...
} 
catch {}

Device.InvokeOnMainThread( () =>
_model.LoginEnabled = true );
});

最新更新