问题描述
我当前正在使用Retrofit 2
,我想在服务器上上传一些照片.我知道,较旧的版本使用TypedFile
类进行上传.如果要使用进度条,则应覆盖TypedFile
类中的writeTo
方法.
I'am currently using Retrofit 2
and i want to upload some photo at my server.I know, that older version uses TypedFile
class for uploading. And if we want to use progress bar with it we should override writeTo
method in TypedFile
class.
使用retrofit 2
库时是否可以显示进度?
Is it possible to show progress when using retrofit 2
library?
推荐答案
首先,您应使用等于或高于2.0 beta2的Retrofit 2版本.其次,创建扩展RequestBody
的新类:
First of all, you should use Retrofit 2 version equal to or above 2.0 beta2.Second, create new class extends RequestBody
:
public class ProgressRequestBody extends RequestBody {
private File mFile;
private String mPath;
private UploadCallbacks mListener;
private String content_type;
private static final int DEFAULT_BUFFER_SIZE = 2048;
public interface UploadCallbacks {
void onProgressUpdate(int percentage);
void onError();
void onFinish();
}
public ProgressRequestBody(final File file, String content_type, final UploadCallbacks listener) {
this.content_type = content_type;
mFile = file;
mListener = listener;
}
@Override
public MediaType contentType() {
return MediaType.parse(content_type+"/*");
}
@Override
public long contentLength() throws IOException {
return mFile.length();
}
@Override
public void writeTo(BufferedSink sink) throws IOException {
long fileLength = mFile.length();
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
FileInputStream in = new FileInputStream(mFile);
long uploaded = 0;
try {
int read;
Handler handler = new Handler(Looper.getMainLooper());
while ((read = in.read(buffer)) != -1) {
// update progress on UI thread
handler.post(new ProgressUpdater(uploaded, fileLength));
uploaded += read;
sink.write(buffer, 0, read);
}
} finally {
in.close();
}
}
private class ProgressUpdater implements Runnable {
private long mUploaded;
private long mTotal;
public ProgressUpdater(long uploaded, long total) {
mUploaded = uploaded;
mTotal = total;
}
@Override
public void run() {
mListener.onProgressUpdate((int)(100 * mUploaded / mTotal));
}
}
}
@Multipart
@POST("/upload")
Call<JsonObject> uploadImage(@Part MultipartBody.Part file);
现在,您可以获取上传进度. 在您的activity
(或fragment
)中:
Now you can get progress of your upload. In your activity
(or fragment
):
class MyActivity extends AppCompatActivity implements ProgressRequestBody.UploadCallbacks {
ProgressBar progressBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
progressBar = findViewById(R.id.progressBar);
ProgressRequestBody fileBody = new ProgressRequestBody(file, this);
MultipartBody.Part filePart =
MultipartBody.Part.createFormData("image", file.getName(), fileBody);
Call<JsonObject> request = RetrofitClient.uploadImage(filepart);
request.enqueue(new Callback<JsonObject>() {
@Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
if(response.isSuccessful()){
/* Here we can equally assume the file has been downloaded successfully because for some reasons the onFinish method might not be called, I have tested it myself and it really not consistent, but the onProgressUpdate is efficient and we can use that to update our progress on the UIThread, and we can then set our progress to 100% right here because the file already downloaded finish. */
}
}
@Override
public void onFailure(Call<JsonObject> call, Throwable t) {
/* we can also stop our progress update here, although I have not check if the onError is being called when the file could not be downloaded, so I will just use this as a backup plan just in case the onError did not get called. So I can stop the progress right here. */
}
});
}
@Override
public void onProgressUpdate(int percentage) {
// set current progress
progressBar.setProgress(percentage);
}
@Override
public void onError() {
// do something on error
}
@Override
public void onFinish() {
// do something on upload finished,
// for example, start next uploading at a queue
progressBar.setProgress(100);
}
}
这篇关于通过Retrofit 2上传图像时是否可以显示进度栏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!