使用Xamarin在Android设备上使用Web服务(不是模拟器):AOT错误

问题描述 投票:0回答:1

我正在使用.Net学习Xamarin和Web App。目标是构建一个Web应用程序(Web服务)和一个Android应用程序,该Android应用程序将使用Web服务。

我已经在Web应用程序上实现了一些基本的东西,我首先尝试使用带有HttpClient的控制台应用程序来访问它。它工作正常:

static HttpClient client = new HttpClient();
HttpResponseMessage response = await client.GetAsync(path); // path is the local path of my IIS server (https://localhost:44331/api/Employees)

下一步是在Xamarin应用程序中执行相同的操作,但是由于我使用的是设备而不是模拟器,因此我的设备无法访问本地IIS服务器。我发现由于有了Conveyor,我可以访问IIS服务器了,所以我添加了Visual Studio的插入方式,向我显示了以下路径:https://192.168.1.25:45455/api/Employees

我尝试在控制台应用程序中使用此路径,并且可以正常工作。我试图通过我的android设备上的浏览器进行访问,它可以正常工作。但是,当我在Xamarin应用程序中使用它时,代码将执行到GetAsync方法(HttpResponseMessage response = await client.GetAsync("https://192.168.1.25:45455/api/Employees");),然后什么也没有发生。没有错误,没有例外,什么都没有。执行就像在这里被阻止。

在输出窗口中,我收到以下消息:

03-15 20:27:04.261 D/Mono    ( 4779): Loading reference 11 of netstandard.dll asmctx DEFAULT, looking for System.Runtime.Serialization, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
03-15 20:27:04.262 D/Mono    ( 4779): Image addref System.Runtime.Serialization[0x789b9fc600] (asmctx DEFAULT) -> System.Runtime.Serialization.dll[0x789b9c8800]: 2
03-15 20:27:04.262 D/Mono    ( 4779): Prepared to set up assembly 'System.Runtime.Serialization' (System.Runtime.Serialization.dll)
03-15 20:27:04.262 D/Mono    ( 4779): Assembly System.Runtime.Serialization[0x789b9fc600] added to domain RootDomain, ref_count=1
03-15 20:27:04.263 D/Mono    ( 4779): AOT: image 'System.Runtime.Serialization.dll.so' not found: dlopen failed: library "System.Runtime.Serialization.dll.so" not found
03-15 20:27:04.263 D/Mono    ( 4779): AOT: image '/Users/builder/jenkins/workspace/archive-mono/2019-08/android/release/sdks/out/android-arm64-v8a-release/lib/mono/aot-cache/arm64/System.Runtime.Serialization.dll.so' not found: (null)
03-15 20:27:04.264 D/Mono    ( 4779): Config attempting to parse: 'System.Runtime.Serialization.dll.config'.
03-15 20:27:04.264 D/Mono    ( 4779): Config attempting to parse: '/Users/builder/jenkins/workspace/archive-mono/2019-08/android/release/sdks/out/android-arm64-v8a-release/etc/mono/assemblies/System.Runtime.Serialization/System.Runtime.Serialization.config'.
03-15 20:27:04.264 D/Mono    ( 4779): Assembly Ref addref netstandard[0x78b6e37a80] -> System.Runtime.Serialization[0x789b9fc600]: 2
03-15 20:27:04.264 D/Mono    ( 4779): Loading reference 0 of System.Runtime.Serialization.dll asmctx DEFAULT, looking for mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
03-15 20:27:04.264 D/Mono    ( 4779): Assembly Ref addref System.Runtime.Serialization[0x789b9fc600] -> mscorlib[0x78bdbf6700]: 52
Loaded assembly: System.Runtime.Serialization.dll [External]
[HotReload] (2020-03-15 20:26:53.4): INFO: HotReload: Initialized Agent.
[HotReload] (2020-03-15 20:27:06.6): INFO: Le rechargement à chaud XAML est connecté et prêt.
03-15 20:27:04.486 D/Mono    ( 4779): DllImport searching in: '__Internal' ('(null)').
03-15 20:27:04.486 D/Mono    ( 4779): Searching for 'java_interop_jnienv_new_string'.
03-15 20:27:04.486 D/Mono    ( 4779): Probing 'java_interop_jnienv_new_string'.
03-15 20:27:04.486 D/Mono    ( 4779): Found as 'java_interop_jnienv_new_string'.
03-15 20:27:04.492 D/Mono    ( 4779): DllImport searching in: '__Internal' ('(null)').
03-15 20:27:04.492 D/Mono    ( 4779): Searching for 'java_interop_jnienv_get_static_object_field'.
03-15 20:27:04.492 D/Mono    ( 4779): Probing 'java_interop_jnienv_get_static_object_field'.
03-15 20:27:04.492 D/Mono    ( 4779): Found as 'java_interop_jnienv_get_static_object_field'.
03-15 20:27:04.502 D/NetworkSecurityConfig( 4779): No Network Security Config specified, using platform default
03-15 20:27:04.503 I/DpmTcmClient( 4779): RegisterTcmMonitor from: com.android.okhttp.TcmIdleTimerMonitor
03-15 20:27:04.648 D/Mono    ( 4779): DllImport searching in: '__Internal' ('(null)').
03-15 20:27:04.648 D/Mono    ( 4779): Searching for 'java_interop_jnienv_call_nonvirtual_boolean_method_a'.
03-15 20:27:04.648 D/Mono    ( 4779): Probing 'java_interop_jnienv_call_nonvirtual_boolean_method_a'.
03-15 20:27:04.649 D/Mono    ( 4779): Found as 'java_interop_jnienv_call_nonvirtual_boolean_method_a'.

所以我认为它可能来自此'AOT:image'System.Runtime.Serialization.dll.so'not found'”。在网上查找时,我发现必须将<AotAssemblies>True</AotAssemblies>设置到project.csproj文件中。首先,我不知道该怎么做。其次,我正在使用Visual Studio社区,并且已经阅读了以下内容:“ Visual Studio的社区版本不支持AOT;并且在过去六个月的某个时间,对Xamarin的更新明确将其强制关闭(如果您手动通过编辑csproj文件打开AOT。)现在必须具有企业版才能通过AOT进行构建。“。

所以现在我有点迷茫,因为我不知道该怎么办。如果有人对我的工作有所了解,那将非常有帮助。

编辑await client.GetAsync()类中的EmployeeServices由以下函数调用:

public static async Task<List<Employee>> GetEmployeesAsync()
    {
        List<Employee> employees = null;
        HttpResponseMessage response = await _client.GetAsync("https://192.168.1.25:45455/api/Employees");
        if (response.IsSuccessStatusCode)
        {
            string json = await response.Content.ReadAsStringAsync();
            employees = JsonConvert.DeserializeObject<List<Employee>>(json);
        }
        return employees;
    }

[GetEmployeesAsync在以下功能中称为MainViewModel.cs

 async Task<List<Employee>> IntermediateMethod()
    {
        return await EmployeesServices.GetEmployeesAsync();
    }

其本身在MainViewModel构造函数中被调用:

public MainViewModel()
    {
        var employeesServices = new EmployeesServices();
        try
        {
             EmployeesList = IntermediateMethod().Result;
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
        //EmployeesList = employeesServices.GetEmployeesStatic();
    }

[MainViewModel被绑定在主页中:

<ContentPage.BindingContext>
    <ViewModels:MainViewModel/>
</ContentPage.BindingContext>
c# web-services xamarin aot
1个回答
0
投票

好,基本上您在构造函数中所做的事情是错误的。

为什么?构造函数不是异步的,并且由于您在哪个上下文中调用该构造函数,您将最终陷入死锁,因为您在Task上调用了.Result

相反,我建议您使用Xamarin.Forms中似乎正在使用的生命周期方法之一。我建议使用OnAppearing替代开始获取数据:

protected override async void OnAppearing()
{
    // get data
}

此外,我也建议封装以Command模式获取数据:

public ICommand GetDataCommand { get; }

然后在ViewModel构造函数中对其进行初始化:

public MainViewModel()
{
    GetDataCommand = new Command(async () => await DoGetDataCommand());
}

然后输入DoGetDataCommand

private async Task DoGetDataCommand()
{
    try
    {
        Employees = await EmployeesServices.GetEmployeesAsync();
    }
    catch (Exception ex)
    {
        // TODO: handle exception
    }
}

然后在OnAppearing呼叫中:GetDataCommand.Execute(null);

另外。非UI代码中所有等待的任务。表示当它们不在ViewModel中时,应考虑在它们上添加.ConfigureAwait(false),例如:

var response = await _client.GetAsync("https://192.168.1.25:45455/api/Employees").ConfigureAwait(false);

此操作不会尝试切换回我们来自的线程。这将限制在线程之间来回切换的开销,如果要切换到的线程已经很忙,则可能导致死锁。

您的ViewModel大致如下:

public class MainViewModel : BaseViewModel
{
    private List<Employee> _employees;

    public ICommand GetDataCommand { get; }

    public List<Employee> Employees
    {
        get => _employees;
        set => SetProperty(ref _employees, value);
    }

    public MainViewModel()
    {
         GetDataCommand = new Command(async () => await DoGetDataCommand());
    }

    private async Task DoGetDataCommand()
    {
        try
        {
            Employees = await EmployeesServices.GetEmployeesAsync();
        }
        catch (Exception ex)
        {
            // TODO: handle exception
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.