我正在开发一个 Android 应用程序,由 Azure 上托管的 ASP.NET Core 应用程序支持。在为 Xamarin.Forms(仅限 Android)项目创建功能之前,我正在使用共享库项目来测试控制台应用程序项目上的基本内容。
以下代码在登录到 Web 服务后运行,其中 Client
是
HttpClient
:
public static async Task<MyClass> GetInformationAsync(string accountId)
{
HttpResponseMessage response = await Client.GetAsync(UriData + "/" + accountId);
response.EnsureSuccessStatusCode();
string responseContent = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<MyClass>(responseContent);
}
在相同的计算机/网络下,代码在控制台应用程序上不到一秒就完成了,但是,在
Xamarin.Forms.Android
项目中它永远不会完成(甚至等了一分钟)。我觉得这很奇怪,因为 Android 客户端可以使用
PostAsync
成功登录到 Web 服务。但是,Android 客户端和控制台客户端的调用方式有所不同
GetInformationAsync
。控制台客户端异步调用时:
private static async void TestDataDownload()
{
...
var data = await WebApiClient.GetInformationAsync(myId);
}
Android客户端同步调用
public void MainPage()
{
...
var data = WebApiClient.GetInformationAsync(myId).Result;
}
GetInformationAsync
的代码,因为它可能是问题根源所在。您可以通过以下方式解决您的问题:
GetInformationAsync
GetInformationAsync
后固定
ConfigureAwait(false)
中的异步调用,以便不在每个方法调用上切换上下文。
GetInformationAsync
方法看起来像:
public static async Task<MyClass> GetInformationAsync(string accountId)
{
var response = await Client.GetAsync(UriData + "/" + accountId).ConfigureAwait(false);
response.EnsureSuccessStatusCode();
var responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
return JsonConvert.DeserializeObject<MyClass>(responseContent);
}
然后,如果您在某个地方调用它,您需要它返回相同的上下文,即如果您需要更新 UI:
var myClass = await GetInformationAsync(accountId);
// update UI here...
否则,如果您
不需要需要返回相同的上下文:
var myClass = await GetInformationAsync(accountId).ConfigureAwait(false);
https://learn.microsoft.com/en-us/xamarin/android/app-fundamentals/http-stack?tabs=windows
android:usesCleartextTraffic="true"
完整的 Mainfest 文件是
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.maximop2p" android:installLocation="auto">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="30" />
<application android:label="MaximoP2P.Android" android:theme="@style/MainTheme"
android:usesCleartextTraffic="true"></application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
</manifest>