从PCL更新文件下载进度到Xamarin.Android

问题描述:

在我们的xamarin.android应用程序中,我们正在从远程服务器下载文件,并且客户端列表行项目更新了进度状态。从PCL更新文件下载进度到Xamarin.Android

为此,我们创建了一个pcl来执行android和ios常见的下载。

从来自新的工作线程xamarin.android应用,我们叫的HttpWebRequest从远程服务器下载文件如下,

ThreadStart downloadThreadStart = new ThreadStart(() => 
    { 
       Stream destinationFileStream = FileUtils.GetFileStream(fileName, info, context); 
       // Call the static method downloadFile present in PCL library class WebRequestHandler 
       WebRequestHandler.downloadFile(listener, fileName, key, destinationFileStream); 
}); 
new Thread(downloadThreadStart).Start(); 

从PCL下载我们使用的await调用写入文件内容方法之后/异步。

await WriteFileContentAsync(response.GetResponseStream(), destFileStream, 
    Convert.ToInt64(size), listener, geoidFileName); 

其用来读取来自httpwebresponse输入流并写入数据以输出数据流文件,其存在于内部存储在下面的代码段中。

private static async Task WriteFileContentAsync(Stream sourceStream, 
     Stream destFileStream, long size, ResponseListener listener, string filename) 
        { 
         byte[] buffer = new byte[BUFFER_SIZE]; 
         //Interface callback sent to the xamarin.android application 
         listener.UpdateDownloadProgress(filename, 0); 
         try 
         { 
          int currentIndex = 0; 
          int bytesRead = await sourceStream.ReadAsync(buffer, 
0, buffer.Length); 

          while (bytesRead > 0) 
          { 
           await destFileStream.WriteAsync(buffer, 0, bytesRead); 
           currentIndex += bytesRead; 
           int percentage = (int)(((double)currentIndex/size) * 100); 
           Debug.WriteLine("Progress value is : " + percentage); 
           listener.UpdateDownloadProgress(filename, percentage); 
           bytesRead = await sourceStream.ReadAsync(buffer, 
0, buffer.Length); 
          } 
          listener.UpdateDownloadProgress(filename, 100); 
          //Send the callback 
          listener.updateDownloadStatus(ResponseStatus.Success, filename); 
         } 
         catch (Exception ex) 
         { 
          Debug.WriteLine("Geoid file write exception : " + ex); 
          listener.updateDownloadStatus(ResponseStatus.Error, filename); 
         } 
         finally 
         { 
          if (sourceStream != null) 
          { 
           sourceStream.Flush(); 
           sourceStream.Dispose(); 
          } 
          if (destFileStream != null) 
          { 
           destFileStream.Flush(); 
           destFileStream.Dispose(); 
          } 
         } 
        } 

一旦回调在xamarin.android收到我们对如下UI线程更新内部运行UI,

public void UpdateDownloadProgress(string filename, int progressValue) 
    { 
      //Skip the progress update if the current and previous progress value is same 
      if (previousProgressValue == progressValue) 
      { 
       return; 
      } 

      int position = findAndUpdateProgressInList(filename); 
      this.itemList[position].ProgressValue = progressValue;   
      RunOnUiThread(() => 
      { 
       this.coordinateAdapter.NotifyDataSetChanged(); 
      }); 
    } 

,但应用程序突然崩溃和关闭。下载状态会在应用程序突然关闭并崩溃后立即更新。卷轴也不光滑。

我们从线程调用下载API。在阅读Xamarin的“报告下载进度”参考链接时说,等待/异步内部调用使用线程池来完成后台任务。

如果我尝试没有线程,一旦我按下了下载图标,UI就会挂起。如果我调用内部线程的UI是响应,并立即崩溃。

PCL异步/等待Xamarin android ui通信不正确。

帮我摆脱这个问题。

我在我的应用程序中做了类似的事情(从概念上讲)。 我通过UI线程通知下载侦听器的方式是通过将(无视图)DownloadManager- 片段RetainInstance设置为true。 这将防止您的片段在配置更改(例如方向更改)时被破坏。

这里是我的代码很短的摘录:

 /// <summary> A non-UI, retaining-instance fragment to internally handle downloading files. </summary> 
     public class DownloadFragment : Fragment 
     { 
      /// <summary> The tag to identify this fragment. </summary> 
      internal new const string Tag = nameof(DownloadFragment); 

      public override void OnCreate(Bundle savedInstanceState) 
      { 
       base.OnCreate(savedInstanceState); 
       RetainInstance = true; 
      } 

      /// <summary> Starts the given download. </summary> 
      public async void RunDownload(Context context, Download download, IDownloadListener listener, 
       IDownloadNotificationHandler handler = null) 
      { 
       // start your async download here, and hook listeners. 
       // Note that listener calls will happen on the UI thread. 
      } 
     } 

所以从您的活动,利用其Tag得到(或创建)该片段,然后用您的下载监听器(S)开始下载。 然后,从您的活动中,您可以拨打NotifyDataSetChanged和类似的方法。

我希望这在解决您的问题的过程中很有用。