简体   繁体   English

下载数据时在MonoTouch中显示微调器

[英]Show spinner in MonoTouch while downloading data

So in my app I have a button that talks to a lib that downloads some data from the internet and filters it. 因此,在我的应用程序中,我有一个与lib对话的按钮,该lib从Internet下载一些数据并对其进行过滤。 When the app is doing this the screen freezes and it looks to the user like the app crashed. 当应用程序执行此操作时,屏幕将冻结,并且在用户看来就像应用程序崩溃一样。 But this is not the case because its downloading data. 但是事实并非如此,因为它正在下载数据。

Here is my code: 这是我的代码:

GetDetailsBtn.TouchUpInside += (sender, e) => {

    var defaults = NSUserDefaults.StandardUserDefaults;

    if (RefNr.Text != string.Empty && RefNr.Text != null) {

        FilteredDataRef = _FetchingData.getTrackTraceData (defaults.StringForKey ("SecurityToken"), RefNr.Text);

        if (FilteredDataRef == null) {
            UIAlertView InvalidAlert = new UIAlertView ("Reference number invalid", "The reference number that you have entered is not linked to the current security code. You can change your security code in the settings.", null, "OK", null);
            InvalidAlert.Show ();

        } else {
            FilteredDataReceived = _FetchingData.FilteringOnReceived (FilteredDataRef);

            FilteredDataPlanned = _FetchingData.FilteringOnPlanned (FilteredDataRef);

            FilteredDataLoadingETA = _FetchingData.FilteringOnLoadingETA (FilteredDataRef);

            FilteredDataLoadingFinal = _FetchingData.FilteringOnLoadingFinal (FilteredDataRef);

            FilteredDataUnloadingETA = _FetchingData.FilteringOnUnloadingETA (FilteredDataRef);

            FilteredDataUnloadingFinal = _FetchingData.FilteringOnUnloadingFinal (FilteredDataRef);   

            this.PerformSegue (MoveToTrackTraceDetailsSegue, this);

            //foreach (string s in FilteredDataPlanned)
            //    Console.WriteLine (s);

        }

    } else {
        UIAlertView InvalidAlert = new UIAlertView ("Reference number cannot be empty", "You did not provide a reference number. We need your reference number to trace identify the shipment you would like to trace.", null, "OK", null);
        InvalidAlert.Show ();
    }
};

Downloading of the data: 数据下载:

public IEnumerable<string> getTrackTraceData (string securityCode, string referenceNumber)
{
    WebRequest request = WebRequest.Create ("http://plex.janssen1877.com/app/life/" + securityCode);

    HttpWebResponse response = (HttpWebResponse)request.GetResponse ();

    Stream dataStream = response.GetResponseStream ();

    StreamReader reader = new StreamReader (dataStream);

    string FetchedData = reader.ReadToEnd ();

    reader.Close ();

    dataStream.Close ();

    response.Close ();

    var FetchingDataItems = FetchedData.Split (new char[] { '\n' });

    if (FetchingDataItems != null) {
        var filteredResult = FetchingDataItems.Where (x => x.Contains (referenceNumber));

        return filteredResult;
    } else {
        return null;
    }
}

Now I want to use a component called BTProgressHUD . 现在,我想使用一个名为BTProgressHUD的组件。 This is just a fancy spinner. 这只是个花哨的微调器。 I thought that if I would put BTProgressHUD.show(); 我以为如果我放BTProgressHUD.show(); to the top of the button action and BTProgressHUD.Dismiss(); 按钮操作和BTProgressHUD.Dismiss();的顶部BTProgressHUD.Dismiss(); to the button it would show when the loading starts and dismiss when its done loading. 按钮,它将在加载开始时显示,并在完成加载后关闭。

This is not the case. 不是这种情况。 It shows very quickly in the new view controller and dismisses again within a second. 它在新的视图控制器中显示非常快,并在一秒钟之内再次关闭。 What am I doing wrong? 我究竟做错了什么?

Edit for exemple: 举例编辑:

public IEnumerable<string> getTrackTraceData (string securityCode, string referenceNumber)
        {


            string url = string.Format ("http://plex.janssen1877.com/app/life/" + securityCode);

            HttpWebRequest HttpRequest = (HttpWebRequest)WebRequest.Create (url);

            string FetchedData = new StreamReader (HttpRequest.GetResponse ().GetResponseStream ()).ReadToEnd ();


            var FetchingDataItems = FetchedData.Split (new char[] { '\n' });

            if (FetchingDataItems != null) {
                var filteredResult = FetchingDataItems.Where (x => x.Contains (referenceNumber));

                return filteredResult;
            } else {
                return null;
            }


        }

Florian, 弗洛里安,

According to .NET documentation and HttpWebRequest GetResponse. 根据.NET文档和HttpWebRequest GetResponse。 How to wait for that response? 如何等待该响应? you need to perform the download (and maybe the parsing) in a async fashion. 您需要以异步方式执行下载(也许是解析)。

The behavior of your actual application is correct. 您的实际应用程序的行为是正确的。 When you perform a sync request in the main thread you freeze the application and hence the UI elements are not updated. 当您在主线程中执行同步请求时,将冻结应用程序,因此不会更新UI元素。 The main thread processes execution in a serial fashion. 主线程以串行方式处理执行。

To avoid this you have two different solutions. 为避免这种情况,您有两种不同的解决方案。 On the one hand, you need to move to an async request. 一方面,您需要移至异步请求。 On the other hand, you can create a background thread (a different path of execution) with a sync request. 另一方面,您可以使用同步请求创建后台线程(不同的执行路径)。 I prefer the former. 我更喜欢前者。 So, for example, after starting the async request, show the indicator. 因此,例如,在启动异步请求之后,显示指示器。 When you have finished (in the callback), dismiss the indicator and perform the segue. 完成后(在回调中),关闭指示器并执行segue。

For example, you can follow the following discussion on how to achieve this: How to use HttpWebRequest (.NET) asynchronously? 例如,您可以按照以下有关如何实现此目的的讨论: 如何异步使用HttpWebRequest(.NET)? .

To understand how the main thread (and the run loop) works, I suggest to read about The pogo stick of NSRunLoop . 为了了解主线程(和运行循环)的工作方式,建议阅读有关NSRunLoop的pogo stick

Hope that helps. 希望能有所帮助。

Edit 编辑

You should use a pattern like the following (source How to use HttpWebRequest (.NET) asynchronously? ): 您应该使用以下模式(源如何异步使用HttpWebRequest(.NET)? ):

HttpWebRequest webRequest;

void StartWebRequest()
{
    webRequest.BeginGetResponse(new AsyncCallback(FinishWebRequest), null);
}

void FinishWebRequest(IAsyncResult result)
{
    webRequest.EndGetResponse(result);
}

It sounds like you're attempting to do all this in the same thread as your UI, which is why your app freezes and waits for processing to finish without showing anything. 听起来您正在尝试在与UI相同的线程中执行所有这些操作,这就是为什么您的应用程序冻结并等待处理完成而不显示任何内容的原因。 I would perform this download operation in a backgroundworker of some sort. 我将在某种类型的背景工作人员中执行此下载操作。 Then I am not sure in Mono but access the main thread before and after and show and dismiss your loading component. 然后我不确定在Mono中,但是在访问前后都可以访问主线程,并显示和关闭加载组件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM