Xamarin Forms - 从 pcl 的视图模型调用休息服务
Xamarin Forms - calling rest service from viewmodel of pcl
我创建了一个 class 连接到 API 以使用 httpclient 检索所需的数据。该文件在视图的代码隐藏文件中被调用并且运行良好。然后我决定实施 MVVM 方法。因此,我将初始化其余服务 class 的代码移到了视图模型中。
这样做之后,我停止获取数据。为了进行调查,我在调试会话中声明了断点,该断点位于我初始化其余服务的行 class。比我执行那条线。通过这样做,我发现抛出了一个巨大的 android 单声道异常并且调试会话停止了。应用程序退出调试会话。
自从我声明在 Xamarin Forms 中开发我的应用程序以来,这是第一次发生这种情况。我不知道为什么它会那样破裂。对你的帮助表示感谢。
这是运行正常的代码。
在文件后面查看代码
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class SubtaskPage : ContentPage
{
protected override void OnAppearing()
{
base.OnAppearing();
PopulateSubtaskData();
}
private async void PopulateSubtaskData()
{
lstSubtasks.IsRefreshing = true;
try
{
RestService rs = new RestService();
SResponse = await rs.GetSubtasksAsync(Convert.ToInt32(Application.Current.Properties["UserId"]));
if (SResponse.Status == 1)
{
lstSubtasks.ItemsSource = SResponse.Subtasks;
}
else
{
await DisplayAlert("Error", SResponse.Message, "Ok");
}
}
catch (Exception E)
{
Debug.WriteLine(@"GetSubtasksAsync -> ERROR {0}", E.Message);
}
lstSubtasks.IsRefreshing = false;
}
}
休息服务class如下
此 class 位于名为 "Services" 的单独文件夹中。出于安全原因,ip 和 url 已更改。
class RestService
{
HttpClient client;
public List<Ticket> Tickets { get; private set; }
string Server1 = "server ip";
string Server2 = "server ip";
public RestService()
{
client = new HttpClient();
client.MaxResponseContentBufferSize = 256000;
}
public async Task<SubtasksResponse> GetSubtasksAsync(int UserId)
{
SubtasksResponse SubtaskResponse = new SubtasksResponse();
string ApiUrl = "URL";
string Url = "";
HttpResponseMessage response;
if (CrossConnectivity.Current.IsConnected)
{
Url = await GetActiveServerAsync();
if (Url != "")
{
var uri = string.Format(Url + ApiUrl, UserId);
try
{
response = await client.GetAsync(uri);
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
SubtaskResponse.Subtasks = JsonConvert.DeserializeObject<List<Ticket>>(content);
SubtaskResponse.Status = 1;
}
else
{
SubtaskResponse.Subtasks = null;
SubtaskResponse.Status = 0;
SubtaskResponse.Message = "Attempt to fetch data from server was unsuccessful. Please try again";
}
}
catch (Exception E)
{
SubtaskResponse.Subtasks = null;
SubtaskResponse.Status = 0;
SubtaskResponse.Message = "Error occured while fetching data from the server. Please try again";
}
}
else
{
SubtaskResponse.Subtasks = null;
SubtaskResponse.Status = 0;
SubtaskResponse.Message = "Remote Server Not Responding! Please try again later";
}
}
else
{
SubtaskResponse.Subtasks = null;
SubtaskResponse.Status = 0;
SubtaskResponse.Message = "No Network Connection Found! Please connect to a network and try again";
}
return SubtaskResponse;
}
}
}
在我将视图模型添加到组合中之前,它一直运行良好。
这就是我在视图模型中调用函数的方式。
async Task<SubtasksResponse> PopulateSubtaskList()
{
RestService rs = new RestService();
IsBusy = true;
_subtaskList = await rs.GetSubtasksAsync(Convert.ToInt32(Application.Current.Properties["UserId"]));
IsBusy = false;
return _subtaskList;
}
"RestService rs = new RestService();" 这是代码中断的行。
这里是代码中断时出现异常的图片。
希望您能清楚地了解情况。如果需要其他信息,请告诉我。
谢谢
不要这样做。如果您想从 mvvm Xamarin Forms 应用调用 rest,我可以建议 Refit。所有困难的工作都已经为您完成并抽象化了。只需几行代码,您就可以 运行.
顺便说一句,您显示的错误消息可能与您的代码无关,而是最近 Xamarin 版本中的错误。看这里:https://bugzilla.xamarin.com/show_bug.cgi?id=56787
解决方法如下
- 下载丢失的 Mono.Posix 文件并解压缩存档。
- 在资源管理器中右键单击 Mono.Posix.dll 文件和 select 属性。
- 检查“数字签名”选项卡以确保文件显示有效的 Xamarin Inc. 签名。
- 在“常规”选项卡的底部,如果出现“取消阻止”复选框,请启用它并 select 确定。 (此复选框的出现取决于文件的下载方式。)
- 对于 Visual Studio 2017,将 Mono.Posix.dll 文件复制到“Xamarin.VisualStudio”扩展目录中。例如,对于企业版的默认安装,将文件复制到:
C:\Program Files (x86)\Microsoft Visual Studio17\Enterprise\Common7\IDE\Extensions\Xamarin.VisualStudio
- 对于Visual Studio 2015,将文件复制到“Xamarin\Xamarin”扩展目录:
C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\Extensions\Xamarin\Xamarin\
- 退出并重新启动 Visual Studio。
有关更多详细信息,请访问上面给出的 link。
我创建了一个 class 连接到 API 以使用 httpclient 检索所需的数据。该文件在视图的代码隐藏文件中被调用并且运行良好。然后我决定实施 MVVM 方法。因此,我将初始化其余服务 class 的代码移到了视图模型中。 这样做之后,我停止获取数据。为了进行调查,我在调试会话中声明了断点,该断点位于我初始化其余服务的行 class。比我执行那条线。通过这样做,我发现抛出了一个巨大的 android 单声道异常并且调试会话停止了。应用程序退出调试会话。 自从我声明在 Xamarin Forms 中开发我的应用程序以来,这是第一次发生这种情况。我不知道为什么它会那样破裂。对你的帮助表示感谢。
这是运行正常的代码。 在文件后面查看代码
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class SubtaskPage : ContentPage
{
protected override void OnAppearing()
{
base.OnAppearing();
PopulateSubtaskData();
}
private async void PopulateSubtaskData()
{
lstSubtasks.IsRefreshing = true;
try
{
RestService rs = new RestService();
SResponse = await rs.GetSubtasksAsync(Convert.ToInt32(Application.Current.Properties["UserId"]));
if (SResponse.Status == 1)
{
lstSubtasks.ItemsSource = SResponse.Subtasks;
}
else
{
await DisplayAlert("Error", SResponse.Message, "Ok");
}
}
catch (Exception E)
{
Debug.WriteLine(@"GetSubtasksAsync -> ERROR {0}", E.Message);
}
lstSubtasks.IsRefreshing = false;
}
}
休息服务class如下 此 class 位于名为 "Services" 的单独文件夹中。出于安全原因,ip 和 url 已更改。
class RestService
{
HttpClient client;
public List<Ticket> Tickets { get; private set; }
string Server1 = "server ip";
string Server2 = "server ip";
public RestService()
{
client = new HttpClient();
client.MaxResponseContentBufferSize = 256000;
}
public async Task<SubtasksResponse> GetSubtasksAsync(int UserId)
{
SubtasksResponse SubtaskResponse = new SubtasksResponse();
string ApiUrl = "URL";
string Url = "";
HttpResponseMessage response;
if (CrossConnectivity.Current.IsConnected)
{
Url = await GetActiveServerAsync();
if (Url != "")
{
var uri = string.Format(Url + ApiUrl, UserId);
try
{
response = await client.GetAsync(uri);
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
SubtaskResponse.Subtasks = JsonConvert.DeserializeObject<List<Ticket>>(content);
SubtaskResponse.Status = 1;
}
else
{
SubtaskResponse.Subtasks = null;
SubtaskResponse.Status = 0;
SubtaskResponse.Message = "Attempt to fetch data from server was unsuccessful. Please try again";
}
}
catch (Exception E)
{
SubtaskResponse.Subtasks = null;
SubtaskResponse.Status = 0;
SubtaskResponse.Message = "Error occured while fetching data from the server. Please try again";
}
}
else
{
SubtaskResponse.Subtasks = null;
SubtaskResponse.Status = 0;
SubtaskResponse.Message = "Remote Server Not Responding! Please try again later";
}
}
else
{
SubtaskResponse.Subtasks = null;
SubtaskResponse.Status = 0;
SubtaskResponse.Message = "No Network Connection Found! Please connect to a network and try again";
}
return SubtaskResponse;
}
}
}
在我将视图模型添加到组合中之前,它一直运行良好。 这就是我在视图模型中调用函数的方式。
async Task<SubtasksResponse> PopulateSubtaskList()
{
RestService rs = new RestService();
IsBusy = true;
_subtaskList = await rs.GetSubtasksAsync(Convert.ToInt32(Application.Current.Properties["UserId"]));
IsBusy = false;
return _subtaskList;
}
"RestService rs = new RestService();" 这是代码中断的行。
这里是代码中断时出现异常的图片。
希望您能清楚地了解情况。如果需要其他信息,请告诉我。 谢谢
不要这样做。如果您想从 mvvm Xamarin Forms 应用调用 rest,我可以建议 Refit。所有困难的工作都已经为您完成并抽象化了。只需几行代码,您就可以 运行.
顺便说一句,您显示的错误消息可能与您的代码无关,而是最近 Xamarin 版本中的错误。看这里:https://bugzilla.xamarin.com/show_bug.cgi?id=56787
解决方法如下
- 下载丢失的 Mono.Posix 文件并解压缩存档。
- 在资源管理器中右键单击 Mono.Posix.dll 文件和 select 属性。
- 检查“数字签名”选项卡以确保文件显示有效的 Xamarin Inc. 签名。
- 在“常规”选项卡的底部,如果出现“取消阻止”复选框,请启用它并 select 确定。 (此复选框的出现取决于文件的下载方式。)
- 对于 Visual Studio 2017,将 Mono.Posix.dll 文件复制到“Xamarin.VisualStudio”扩展目录中。例如,对于企业版的默认安装,将文件复制到: C:\Program Files (x86)\Microsoft Visual Studio17\Enterprise\Common7\IDE\Extensions\Xamarin.VisualStudio
- 对于Visual Studio 2015,将文件复制到“Xamarin\Xamarin”扩展目录: C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\Extensions\Xamarin\Xamarin\
- 退出并重新启动 Visual Studio。
有关更多详细信息,请访问上面给出的 link。