【问题标题】:Xamarin HttpClient how to fetch json and use itXamarin HttpClient 如何获取 json 并使用它
【发布时间】:2017-05-01 20:20:19
【问题描述】:

首先我想说的是,我一直在反复阅读https://developer.xamarin.com/guides/xamarin-forms/cloud-services/consuming/rest/ 指南,但没有帮助。

我有一个 phpwebservice,它在被问到时返回 json:

    <?php

include("../include/class.pdogsb.inc.php");


$pdo = PdoGsb::getPdoGsb();


$tabCabinets = $pdo->getLesCabinets();



    header('Content-type: application/json');
    echo json_encode(array('cabinets'=>$tabCabinets));

?>

它给出了这种类型的响应

cabinets": [

    {
        "0": "1",
        "1": "2,2891506",
        "2": "48,8618687",
        "3": "75016",
        "4": "Paris",
        "5": "1 Avenue Gustave V de Suède",
        "id": "1",
        "longitudeGPS": "2,2891506",
        "latitudeGPS": "48,8618687",
        "cp": "75016",
        "ville": "Paris",
        "rue": "1 Avenue Gustave V de Suède"
    },

在我的 xamarin PCL 项目中,我创建了一个方法,当我加载视图以获取该 json 数据时使用该方法。

    using Newtonsoft.Json;
    using suivAAndroid.Models;
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Net.Http;
    using System.Text;
    using System.Threading.Tasks;

    namespace suivAAndroid.ViewModel
    {
        public partial class CreerVisiteViewModel : INotifyPropertyChanged
        {
            #region propriétés
            private Cabinet unCabinet;
            private Medecin unMedecin;

            public event PropertyChangedEventHandler PropertyChanged;

            #endregion

            #region methods
            public CreerVisiteViewModel()
            {
                loadcabinets();
            }
            private async Task loadcabinets()
            {
                List<Cabinet> listeCabinets = null;
                HttpClient clientCabinets = new HttpClient();
                string url = "http://10.0.0.5/ppe3JoJuAd/gsbAppliFraisV2/webservices/w_cabinet.php";
//does not read the code after this line
                var response = await clientCabinets.GetAsync(new Uri(url));
                string jsonString = await response.Content.ReadAsStringAsync();
                listeCabinets = JsonConvert.DeserializeObject<List<Cabinet>>(jsonString);
            }

            #endregion
        }
    }

我的问题是,在执行和调试应用程序时,编译器不在string url = "10.0.0.5/ppe3JoJuAd/gsbAppliFraisV2/webservices/w_cabinet.php"; 行之后。相反,它返回到loadcabinets();,这意味着客户端永远不会获取 json 数据。

我能做什么?

编辑:用最近的答案更新代码

我创建了一个 BaseViewModel 我在其中实现了 Icommand 接口

public class RelayCommandAsync : ICommand
    {
        private Func<object, Task> _action;
        private Task _task;

        public RelayCommandAsync(Func<object, Task> action)
        {
            _action = action;
        }

        public bool CanExecute(object parameter)
        {
            return _task == null || _task.IsCompleted;
        }

        public event EventHandler CanExecuteChanged;

        public async void Execute(object parameter)
        {
            _task = _action(parameter);
            OnCanExecuteChanged();
            //await _task;
            //OnCanExecuteChanged();
        }

        private void OnCanExecuteChanged()
        {
            var handler = this.CanExecuteChanged;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }
    }

这是我之前的 ViewModel 中的结果

#region methods
        public CreerVisiteViewModel()
        {


        }
        #endregion
        #region Methods
        public async Task<List<Cabinet>> loadcabinetsAsync()
        {
            List<Cabinet> listeCabinets = null;
            HttpClient clientCabinets = new HttpClient();
            try
            {
                string url = "http://10.0.0.5/ppe3JoJuAd/gsbAppliFraisV2/webservices/w_cabinet.php";
                var uri = new Uri(string.Format(url, string.Empty));
                var response = await clientCabinets.GetAsync(uri);
                string jsonString = await response.Content.ReadAsStringAsync();
                listeCabinets = JsonConvert.DeserializeObject<List<Cabinet>>(jsonString);

            }
            catch (Exception e)
            {

            }
            return listeCabinets;
        }
        #endregion


        #region ICommand
        public ICommand ExecuteLoadCabinetAsync { get { return new RelayCommandAsync(x => loadcabinetsAsync()); } }
        #endregion

编译器没有读取所有方法的代码仍然无法解决我的问题,我还能做些什么?

【问题讨论】:

    标签: c# json xamarin


    【解决方案1】:

    这里有几个问题:

    1. 您正在调用异步方法而不等待它。
    2. 您正在构造函数中调用异步方法
    3. 您正在一个接一个地调用多个异步方法,而没有使用 ConfigureAwait(false),这意味着您正在来回切换上下文
    4. 您的 URL 没有有效的方案,因此您可能会遇到异常

    如果您想使用 MVVM 模式,您可以将代码包装在 ICommand 中,然后执行该命令以填充 ObservableCollection。该命令的执行将在 ViewController/Activity/Page 的生命周期事件中发生,具体取决于您所在的平台。

    【讨论】:

    • 如何解决 1 和 2 ?我不知道 3。确实,我抛出了一个无效的 uri 异常,我通过将 http 放在整个字符串之前解决了这个异常。
    • 由于构造函数不能是异步的,所以将 loadcabinets(); 调用包装在一个任务中:Task.Run(async () =&gt; await loadcabinets());
    • 按照建议使用ICommand 并执行。 MvvmCross、ReactiveUI、MvvmLight 等框架已经有了可供使用的实现。
    猜你喜欢
    • 2018-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-02
    • 2022-10-12
    • 2019-07-03
    • 2019-03-21
    • 1970-01-01
    相关资源
    最近更新 更多