Summary
The usage of retrofit is described in detail in this article in Retrofit2.0. And in the retrofit we can download the files through the responsebody. However, the retrofit does not provide us with the interface to display the download progress. In the project, if the user downloads a file, can not show users real-time download progress, so the user experience is very poor. So here's how to track download progress in real time for downloads in retrofit for files. Demo
implementation of retrofit file download progress update
In retrofit2.0 he relies on okhttp, so if we need to solve this problem we need to start with this okhttp. There is a dependency pack Okio in the okhttp. Okio is also developed by Square, which complements Java.io and Java.nio, and uses it to make it easier to access, store, and process data. Here you need to use the source class in Okio. The source here can be seen as InputStream. The detailed use of Okio is not covered here. Here's a look at the concrete implementation.
Here we first write an interface to monitor the progress of the download. For downloading files, we need to know the progress of the download, the total size of the file, and whether the operation is complete. So there is an interface like the one below.
Package com.ljd.retrofit.progress;
/**
* Created by Ljd on 3/29/16.
* * Public
interface Progresslistener {
/**
* @param progress has downloaded or uploaded bytes
* @param Total bytes
* @param done is completed
/void OnProgress (long progress, long Total, Boolean performed);
}
1 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4 5 6 7 8 9 10 11 The 12 13
For downloading files we need to rewrite some of the methods in the Responsebody class.
Package com.ljd.retrofit.progress;
Import java.io.IOException; Import OKHTTP3.
mediatype; Import OKHTTP3.
Responsebody; Import Okio.
Buffer; Import Okio.
Bufferedsource; Import Okio.
Forwardingsource; Import Okio.
Okio; Import Okio.
Source;
/** * Created by Ljd on 3/29/16.
* * public class Progressresponsebody extends Responsebody {private final responsebody responsebody;
Private final Progresslistener Progresslistener;
Private Bufferedsource Bufferedsource; Public Progressresponsebody (Responsebody responsebody, Progresslistener progresslistener) {this.responseBody = re
Sponsebody;
This.progresslistener = Progresslistener;
@Override Public mediatype ContentType () {return responsebody.contenttype ();
@Override public Long ContentLength () {return responsebody.contentlength (); @Override public Bufferedsource Source () {if (Bufferedsource = = null) {Bufferedsource = O Kio.buffer (Source (Responsebody.source ()));
return bufferedsource; Private source Source {return new Forwardingsource (source) {Long Totalbytesrea
D = 0L; @Override public Long Read (Buffer sink, long ByteCount) throws IOException {Long bytesread =
Super.read (sink, byteCount); Totalbytesread + = Bytesread!=-1?
bytesread:0;
Progresslistener.onprogress (Totalbytesread, Responsebody.contentlength (), bytesread = = 1);
return bytesread;
}
};
}
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26-27--28 29---30 31--32 33 34 35 36 37 38-39 40 41 42 45 46 47 48 49 50 51 52 53 54 55 56 57 58 1 2 3 4 5 6 7 8 9 10 11 12-13--14 15---16 17--18 19 20 21 22 23 24-25 26 27 28 0 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57-58
In the Progressresponsebody class above, we calculate the number of bytes that have been read and call the Progresslistener interface. So this Progresslistener interface is running in a child thread.
Let's take a look at how to use this progressresponsebody.
Package com.ljd.retrofit.progress;
Import Android.util.Log;
Import java.io.IOException; Import OKHTTP3.
Interceptor; Import OKHTTP3.
Okhttpclient;
/** * Created by Ljd on 4/12/16.
* * Public class Progresshelper {private static Progressbean Progressbean = new Progressbean ();
private static Progresshandler Mprogresshandler; public static Okhttpclient.builder addprogress (Okhttpclient.builder Builder) {if (Builder = null) {b
Uilder = new Okhttpclient.builder (); Final Progresslistener Progresslistener = new Progresslistener () {//This method runs in a child thread @Overri De public void onprogress (long progress, long total, Boolean done) {LOG.D ("Progress:", String.)
Format ("%d%% done\n", (* progress)/total);
if (Mprogresshandler = = null) {return;
} progressbean.setbytesread (progress); Progressbean.setcontentlength (TotaL);
Progressbean.setdone (done);
Mprogresshandler.sendmessage (Progressbean);
}
};
Add interceptors, customize Responsebody, add download Progress builder.networkinterceptors (). Add (New Interceptor () {@Override Public OKHTTP3. Response Intercept (Chain Chain) throws IOException {okhttp3.
Response originalresponse = Chain.proceed (Chain.request ()); Return Originalresponse.newbuilder ()-Body (new Progressresponsebody (originalresponse.body), Progr
Esslistener)). Build ();
}
});
return builder;
public static void Setprogresshandler (Progresshandler progresshandler) {mprogresshandler = Progresshandler; }
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26-27--28 29---30 31--32 33 34 35 36 37 38-39 40 41 42 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 1 2 3 4 5 6 7 8 9 10 11-12--13 14---15 16--17 18 19 20 21 22 23-24 25 26 27 9 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58-59
We use our custom progressresponsebody by adding an interceptor to the okhttpclient. And here we can implement the Progresslistener interface. To get the download progress. But there is still a problem here, just speaking of the Progresslistener interface running in a child thread. That is, we are unable to perform UI operations in the Progresslistener interface. The progress of getting a file download is often the need for a progress bar for UI display. Obviously this is not the result we want.
At this time we need to use the handler. We can do this by handler the Progresslistener data in the child thread to the UI thread. In other words, our operation in the Progresslistener interface simply sends its parameters through the handler. It is clear that in the above code we send messages through Progresshandler. Then take a look at the specific operation.
Here we create an object that holds the parameters in the Progresslistener.
Package Com.example.ljd.retrofit.pojo;
Import java.util.ArrayList;
Import java.util.List;
/** * Created by Ljd on 3/29/16.
* * Public class Retrofitbean {private Integer total_count;
Private Boolean incompleteresults;
Private list<item> items = new arraylist<item> (); /** * * @return * The totalcount/public Integer Gettotalcount () {return Total_coun
T /** * * @param totalcount * The total_count/public void Settotalcount (Integer totalc
Ount) {this.total_count = TotalCount;
}/** * * @return * The incompleteresults/public Boolean getincompleteresults () {
return incompleteresults; }/** * * @param incompleteresults * The incomplete_results/public void Setincompleter
Esults (Boolean incompleteresults) {this.incompleteresults = Incompleteresults; }
/**
*
* @return * the items */public list<item> GetItems () {return items; }
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23-24