Android 使用内部库接口回调将同步请求转换为异步
Android convert Synchronous request to asynchronous using internal library Interface Callback
我在我的应用程序中使用 .aar 库。
它有一个网络委托接口,我需要覆盖它。
ApiResponse executeApiCall(String url, HTTPMethod method, String params)
我正在使用 Retrofit 进行网络调用。我需要将同步调用转换为异步使用。
@Override
public ApiResponse executeApiCall(String url, HTTPMethod method, String params) {
ApiResponse apiResponse;
try {
// Synchronous Call
Call<String> call = RestClient.get().getStringResponse(url, method, params);
Response<String> response = call.execute();
apiResponse = new ApiResponse(response.code(), response.body());
} catch (Exception e) {
apiResponse = new ApiResponse();
}
return apiResponse;
}
现在我被困在如何在我必须覆盖的网络接口中使用异步调用。
@Override
public ApiResponse executeApiCall(String url, HTTPMethod method, String params) {
ApiResponse apiResponse;
// Asynchronous Call
Call<String> call = RestClient.get().getStringResponse(url, method, params);
call.enqueue(new Callback<String>() {
@Override
public void onResponse(@NotNull Call<String> call, @NotNull Response<String> response) {
if (response.isSuccessful()) {
apiResponse = new ApiResponse(response.code(), response.body());
}
}
@Override
public void onFailure(@NotNull Call<String> call, @NotNull Throwable t) {
apiResponse = new ApiResponse();
}
});
return apiResponse;
}
我无法更改网络委托界面。我必须覆盖它,我需要使用改造异步。
非常感谢您的反馈。谢谢大家。
我在另一个堆栈溢出线程上找到了一些代码。以下是您可以如何使用代码来实现您正在寻找的东西。
这是class
public abstract class AsyncRunnable<T> {
protected abstract void run(AtomicReference<T> notifier);
protected final void finish(AtomicReference<T> notifier, T result) {
synchronized (notifier) {
notifier.set(result);
notifier.notify();
}
}
public static <T> T wait(AsyncRunnable<T> runnable) {
final AtomicReference<T> notifier = new AtomicReference<>();
// run the asynchronous code
runnable.run(notifier);
// wait for the asynchronous code to finish
synchronized (notifier) {
while (notifier.get() == null) {
try {
notifier.wait();
} catch (InterruptedException ignore) {}
}
}
// return the result of the asynchronous code
return notifier.get();
}
}
你可以这样使用它
ApiResponse result = AsyncRunnable.wait(new AsyncRunnable<ApiResponse>() {
@Override
public void run(final AtomicReference<String> notifier) {
// here goes your async code, e.g.:
new Thread(new Runnable() {
@Override
public void run() {
Call<String> call =
RestClient.get().getStringResponse(url, method, params);
call.enqueue(new Callback<String>() {
@Override
public void onResponse(@NotNull Call<String> call,
@NotNull
Response<String> response) {
if (response.isSuccessful()) {
apiResponse = new
ApiResponse(response.code(),
response.body());
finish(notifier, apiResponse);
}
}
@Override
public void onFailure(@NotNull Call<String> call, @NotNull Throwable t) {
apiResponse = new ApiResponse();
finish(notifier, apiResponse);
}
});
}
}).start();
}
});
我们等待来自回调的响应并通知 AsyncRunnable class。
我觉得你,我遇到了一个类似的问题,一个库需要在 UI 线程上做繁重的工作(非 UI)。是的,听起来像是精神病患者的 lib。协程 runBlocking
是你的朋友。我知道您要求的是 rx-java 解决方案,但无法在这方面击败协程。
/**
* You can edit, run, and share this code.
* play.kotlinlang.org
*/
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
fun main() {
val apiResponse = executeApiCall()
println(apiResponse) // prints "response"
println("goodbye, world!!!")
}
/**
* Synchronous function that waits for coroutine to finish
*/
fun executeApiCall():String {
return runBlocking(Dispatchers.IO){
retrofitCall()
}
}
/**
* Method that invokes Retrofit call in the background.
*/
suspend fun retrofitCall():String{
// RestClient.get() ...
return "response"
}
请注意,如果您从 UI 线程调用 executeApiCall
,您仍然会阻塞 UI 线程。因此,如果您在 activity 或片段(gradle 依赖项 androidx.lifecycle:lifecycle-runtime-ktx:2.1.0
)内,则可能需要 lifecycleScope.launch{executeApiCall() }
之类的东西,否则可能需要 CoroutineScope(Dispatchers.IO).launch { executeApiCall() }
。
我在我的应用程序中使用 .aar 库。 它有一个网络委托接口,我需要覆盖它。
ApiResponse executeApiCall(String url, HTTPMethod method, String params)
我正在使用 Retrofit 进行网络调用。我需要将同步调用转换为异步使用。
@Override
public ApiResponse executeApiCall(String url, HTTPMethod method, String params) {
ApiResponse apiResponse;
try {
// Synchronous Call
Call<String> call = RestClient.get().getStringResponse(url, method, params);
Response<String> response = call.execute();
apiResponse = new ApiResponse(response.code(), response.body());
} catch (Exception e) {
apiResponse = new ApiResponse();
}
return apiResponse;
}
现在我被困在如何在我必须覆盖的网络接口中使用异步调用。
@Override
public ApiResponse executeApiCall(String url, HTTPMethod method, String params) {
ApiResponse apiResponse;
// Asynchronous Call
Call<String> call = RestClient.get().getStringResponse(url, method, params);
call.enqueue(new Callback<String>() {
@Override
public void onResponse(@NotNull Call<String> call, @NotNull Response<String> response) {
if (response.isSuccessful()) {
apiResponse = new ApiResponse(response.code(), response.body());
}
}
@Override
public void onFailure(@NotNull Call<String> call, @NotNull Throwable t) {
apiResponse = new ApiResponse();
}
});
return apiResponse;
}
我无法更改网络委托界面。我必须覆盖它,我需要使用改造异步。
非常感谢您的反馈。谢谢大家。
我在另一个堆栈溢出线程上找到了一些代码。以下是您可以如何使用代码来实现您正在寻找的东西。
这是class
public abstract class AsyncRunnable<T> {
protected abstract void run(AtomicReference<T> notifier);
protected final void finish(AtomicReference<T> notifier, T result) {
synchronized (notifier) {
notifier.set(result);
notifier.notify();
}
}
public static <T> T wait(AsyncRunnable<T> runnable) {
final AtomicReference<T> notifier = new AtomicReference<>();
// run the asynchronous code
runnable.run(notifier);
// wait for the asynchronous code to finish
synchronized (notifier) {
while (notifier.get() == null) {
try {
notifier.wait();
} catch (InterruptedException ignore) {}
}
}
// return the result of the asynchronous code
return notifier.get();
}
}
你可以这样使用它
ApiResponse result = AsyncRunnable.wait(new AsyncRunnable<ApiResponse>() {
@Override
public void run(final AtomicReference<String> notifier) {
// here goes your async code, e.g.:
new Thread(new Runnable() {
@Override
public void run() {
Call<String> call =
RestClient.get().getStringResponse(url, method, params);
call.enqueue(new Callback<String>() {
@Override
public void onResponse(@NotNull Call<String> call,
@NotNull
Response<String> response) {
if (response.isSuccessful()) {
apiResponse = new
ApiResponse(response.code(),
response.body());
finish(notifier, apiResponse);
}
}
@Override
public void onFailure(@NotNull Call<String> call, @NotNull Throwable t) {
apiResponse = new ApiResponse();
finish(notifier, apiResponse);
}
});
}
}).start();
}
});
我们等待来自回调的响应并通知 AsyncRunnable class。
我觉得你,我遇到了一个类似的问题,一个库需要在 UI 线程上做繁重的工作(非 UI)。是的,听起来像是精神病患者的 lib。协程 runBlocking
是你的朋友。我知道您要求的是 rx-java 解决方案,但无法在这方面击败协程。
/**
* You can edit, run, and share this code.
* play.kotlinlang.org
*/
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
fun main() {
val apiResponse = executeApiCall()
println(apiResponse) // prints "response"
println("goodbye, world!!!")
}
/**
* Synchronous function that waits for coroutine to finish
*/
fun executeApiCall():String {
return runBlocking(Dispatchers.IO){
retrofitCall()
}
}
/**
* Method that invokes Retrofit call in the background.
*/
suspend fun retrofitCall():String{
// RestClient.get() ...
return "response"
}
请注意,如果您从 UI 线程调用 executeApiCall
,您仍然会阻塞 UI 线程。因此,如果您在 activity 或片段(gradle 依赖项 androidx.lifecycle:lifecycle-runtime-ktx:2.1.0
)内,则可能需要 lifecycleScope.launch{executeApiCall() }
之类的东西,否则可能需要 CoroutineScope(Dispatchers.IO).launch { executeApiCall() }
。