Flutter Dio Package: How to listen to download progress from another class?
Asked Answered
G

2

6

I have a DownloadsService class that handles downloading of file using dio package. I want to listen to the download progress from my ViewModel class that implements the downloadFile method inside my DownloadService class. How do I do this?

Here's my code snippet for DownloadsService class:

class DownloadsService {
   final String urlOfFileToDownload = 'http://justadummyurl.com/'; //in my actual app, this is user input
   final String filename = 'dummyfile.jpg';
   final String dir = 'downloads/$filename'; //i'll have it saved inside internal storage downloads directory

   void downloadFile() {
     Dio dio = Dio();
     dio.download(urlOfFileToDownload, '$dir/$filename', onReceiveProgress(received, total) {
        int percentage = ((received / total) * 100).floor(); //this is what I want to listen to from my ViewModel class
     });
   }
}

and this is my ViewModel class:

class ViewModel {
   DownloadsService _dlService = DownloadsService(); //note: I'm using get_it package for my services class to make a singleton instance. I just wrote it this way here for simplicity..

      void implementDownload() {

       if(Permission.storage.request().isGranted) { //so I can save the file in my internal storage
          _dlService.downloadFile();

        /*
         now this is where I'm stuck.. My ViewModel class is connected to my View - which displays
         the progress of my download in a LinearProgressIndicator. I need to listen to the changes in
         percentage inside this class.. Note: my View class has no access to DownloadsService class. 
       */

      }        
   }
}

The Dio documentation provides an example on how to make the response type into a stream/byte.. But it doesn't give any example on how to do it when downloading a file. Can someone point me to a right direction? I'm really stuck at the moment.. Thank you very much!

Gains answered 14/6, 2020 at 21:17 Comment(0)
O
2

I had exactly this issue

I solved issue with dependency injection from my model

actually I defined progress field(double) into my model for listening to download percent and also defined an object from my model into GetX controller(u can use any dependency injection like getIt, ...) so with live data mechanism , this issue will solve so easily

Ortrude answered 10/4, 2022 at 10:34 Comment(0)
P
1

If the View creates the ViewModel, then you must define PublishSubject variable in View class, then pass it to the ViewModel, and also pass it to the DownloadsService as a parameter

like this :

class ViewModel {
       PublishSubject publishSubject;
       ViewModel(this.publishSubject);
       DownloadsService _dlService = DownloadsService();   
          void implementDownload() { 
           if(Permission.storage.request().isGranted) {  
              _dlService.downloadFile(publishSubject); 
          }        
       }
    }

So that the View listens to the changes that will happen before downloadFile method, Which in turn sends the changes sequentially

like this:

void downloadFile(PublishSubject publishSubject) {
     Dio dio = Dio();
     dio.download(urlOfFileToDownload, '$dir/$filename', 
        onReceiveProgress(received,total) {
        int percentage = ((received / total) * 100).floor(); 
        publishSubject.add(percentage);
     });
   }

So that the interface listens to the changes that will happen before

like this:

class View {
  PublishSubject publishSubject = PublishSubject();
  ViewModel viewModel;
  View(){
    publishSubject.listen((value) {
      // the value is percentage.
      //can you refresh view or do anything
    });
   viewModel = ViewModel(publishSubject);
  }  
}
Pulcheria answered 14/6, 2020 at 22:7 Comment(2)
Hey man, thanks for responding. My View class really, is just my UI code. I strictly don't want to put any business logic inside my View class. What I wanted to do is that, my ViewModel class will listen to the DownloadsService class, then pass that current value to View class. So the only thing that my View class does is displaying the data in UI.Gains
You're welcome, I understand what you really want, you can define the 'publishSubject' variable in 'ViewModel' and listening to 'DownloadsService'Pulcheria

© 2022 - 2024 — McMap. All rights reserved.