从视图模型交叉调用Web服务
本文关键字:调用 Web 服务 视图 模型 | 更新日期: 2023-09-27 18:10:13
我是MvvmCross和Android开发的新手。我需要调用POST数据到我的视图模型中的JSON web服务。然后,我需要在UI中显示web服务的结果。我的视图模型的要点如下:
public class MyViewModel : MvxViewModel
{
public override void Start()
{
base.Start();
}
public event EventHandler<EventArgs> Service_Finished;
public void CallService()
{
string url = GetServiceUrl();
WebRequest serviceRequest = HttpWebRequest.Create(url);
serviceRequest.Method = "POST";
serviceRequest.ContentType = "application/json";
serviceRequest.BeginGetRequestStream(new AsyncCallback(ServiceBeginGetRequestStreamCallback), serviceRequest);
}
private void ServiceBeginGetRequestStreamCallback(IAsyncResult ar)
{
string json = GetJson();
HttpWebRequest myWebRequest = (HttpWebRequest)(ar.AsyncState);
using (Stream postStream = myWebRequest.EndGetRequestStream(ar))
{
byte[] byteArray = Encoding.UTF8.GetBytes(json);
postStream.Write(byteArray, 0, byteArray.Length);
}
myWebRequest.BeginGetResponse(new AsyncCallback(Service_Completed), myWebRequest);
}
private void Service_Completed(IAsyncResult result)
{
if (Service_Finished != null)
Service_Finished(this, new EventArgs());
}
}
在View (UI)代码中,我为Service_Finished
事件添加了一个事件处理程序。我注意到,我可以成功地抛出事件从"CallService
"方法在我的视图模型。但是,如果我尝试从ServiceBeginGetRequestStreamCallback
或Service_Completed
部分触发Service_Finished
,则该事件永远不会在UI中触发。
由于视图模型是在一个可移植的类库,我不知道如何调试这一事实。此时,我知道CallService正在被成功调用。然而,我不知道我在ServiceBeginGetRequestStreamCallback
内的位置,如果我甚至到达Service_Completed
。
我知道从我的Windows Phone开发经验,我需要检查,看看我是否在UI线程,如果不是,我必须做一些部署的东西。但是,使用MvvmCross方法,我不确定a)如果我必须这样做,b)如果这是一个选项,因为视图模型应该与Android和iOS一起工作。无论如何,必须有一种方法a)从视图模型调用web服务,b)向视图发送消息,以便UI可以更新。不幸的是,我似乎弄不明白。有人能告诉我我做错了什么吗?
谢谢
一般来说,我把这种WebService调用放在Model中而不是ViewModel中——这使得ViewModel和WebService客户端代码更易于重用。
一些简单的例子如下:
- twittersearch示例- https://github.com/slodge/MvvmCross/tree/v3/Sample%20-%20TwitterSearch
- 呆伯特样本- https://github.com/slodge/MvvmCross-Tutorials/tree/master/DailyDilbert
我知道从我的Windows Phone开发经验,我需要检查,看看我是否在UI线程,如果不是,我必须做一些部署的东西。但是,对于MvvmCross方法,我不确定a)如果我必须这样做
是的,所有来自ViewModel->View的通信都应该在UI线程上。
b)如果这是一个选项,因为视图模型应该与Android和iOS同时工作。
MvvmCross提供了一个接口,允许您将执行封送到UI线程上。在ViewModel中,这很容易通过调用InvokeOnMainThread(() => { /* your code */ })
在幕后,MvvmCross也会将所有RaisePropertyChanged
的执行编组到UI线程。注意 - ObservableCollection
更新不会自动封送-这是因为ObservableCollection
是一个存在于MvvmCross之外的类。
无论如何,必须有一种方法a)从视图模型调用web服务和
参见上面的示例
b)向视图发送消息,以便更新UI。
一般来说,你不应该通过事件发送这类消息。
相反,你应该:
- 更新ViewModel属性
- (偶尔)通过信使发送消息