gpt4 book ai didi

android - 如何在进度条(Android)中显示POST请求的进度?

转载 作者:行者123 更新时间:2023-11-29 22:42:49 26 4
gpt4 key购买 nike

我正在使用 Retrofit2-library 执行 POST 请求,以将文件上传到我的 api。我怎样才能以某种方式表示用户知道应用程序正在做某事的进度?

我的最终目标是将其链接到进度条或其他东西,但首先如何从 retrofit2 获取 POST 的进度?

最佳答案

如果您使用分段上传:

创建一个扩展 RequestBody 的新类:

public class ProgressRequestBody extends RequestBody {
private static final int DEFAULT_BUFFER_SIZE = 2048;
private UploadProgressListener listener;
private File file;
private String path;
private String content_type;

public interface UploadProgressListener {
void onProgressUpdate(int percentage);
}

public ProgressRequestBody(final File file, String contentType, final UploadProgressListener listener) {
this.file = file;
this.listener = listener;
this.content_type = contentType;
}

@Override
public MediaType contentType() {
return MediaType.parse(content_type+"/*");
}

@Override
public long contentLength() throws IOException {
return file.length();
}

@Override
public void writeTo(BufferedSink sink) throws IOException {
long fileLength = file.length();
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
FileInputStream in = new FileInputStream(file);
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() {
listener.onProgressUpdate((int)(100 * mUploaded / mTotal));
}
}
}

然后创建你的 api 接口(interface):

@Multipart
@POST("/your_upload_url")
Call<YourJsonObject> uploadImage(@Part MultipartBody.Part file);

像这样使用它:

  ProgressRequestBody fileBody = new ProgressRequestBody(file, "your content type", new ProgressRequestBody.UploadProgressListener() {
@Override
public void onProgressUpdate(int percentage) {
// Update the progressbar
}
}););
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()){
//Do something
}
}

@Override
public void onFailure(Call<JsonObject> call, Throwable t) {

}
});

完成。

使用拦截器的替代方法:

我们可以在okhttp客户端添加一个拦截器来跟踪上传进度。

首先,你需要像这样扩展okhttp的ResponseBody类:

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;

public class ProgressResponseBody extends ResponseBody {

private final ResponseBody responseBody;
private final ProgressListener progressListener;
private BufferedSource bufferedSource;

ProgressResponseBody(ResponseBody responseBody, ProgressListener progressListener) {
this.responseBody = responseBody;
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 = Okio.buffer(source(responseBody.source()));
}
return bufferedSource;
}

private Source source(Source source) {
return new ForwardingSource(source) {
long totalBytesRead = 0L;

@Override
public long read(Buffer sink, long byteCount) throws IOException {
long bytesRead = super.read(sink, byteCount);
// read() returns the number of bytes read, or -1 if this source is exhausted.
totalBytesRead += bytesRead != -1 ? bytesRead : 0;
progressListener.update(totalBytesRead, responseBody.contentLength(), bytesRead == -1);
return bytesRead;
}
};
}
}

interface ProgressListener {
void update(long bytesRead, long contentLength, boolean done);
}

这个类负责跟踪进度和更新监听器。

然后你必须创建一个新的监听器实例:

final ProgressListener progressListener = new ProgressListener() {
boolean firstUpdate = true;

@Override public void update(long bytesRead, long contentLength, boolean done) {
if (done) {
System.out.println("completed");
} else {
if (firstUpdate) {
firstUpdate = false;
if (contentLength == -1) {
System.out.println("content-length: unknown");
} else {
System.out.format("content-length: %d\n", contentLength);
}
}

System.out.println(bytesRead);

if (contentLength != -1) {
System.out.format("%d%% done\n", (100 * bytesRead) / contentLength);
}
}
}
};

然后你必须给你的okhttp客户端添加一个拦截器:

OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addNetworkInterceptor(chain -> {
Response originalResponse = chain.proceed(chain.request());
return originalResponse.newBuilder()
.body(new ProgressResponseBody(originalResponse.body(), progressListener))
.build();
})
.build();

最后,将新客户端添加到您的改造中:

Retrofit retrofit = new Retrofit.Builder()
.baseUrl("some url")
.client(okHttpClient)
.build();

请注意,此方法会跟踪所有 API 调用,而不仅仅是用于上传的特定 API,要解决此问题,您可以将请求 URL 传递给 ProgressListener.update() 然后您可以使用 EventBus发布包含 URL 和进度的事件。如果您对最后一部分有任何疑问,请随时提出。

附言该方法基于官方okhttp示例。

关于android - 如何在进度条(Android)中显示POST请求的进度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58818572/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com