使用这种类型的Gson注册InstanceCreator可能会解决此问题

时间:2019-06-17 14:33:23

标签: android kotlin-coroutines

在我的android应用中:

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory;

import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

private static Retrofit.Builder builder = new Retrofit.Builder()
            .baseUrl(BuildConfig.API_BASE_URL)
            .addConverterFactory(GsonConverterFactory.create(gson))
            .addCallAdapterFactory(CoroutineCallAdapterFactory.Companion.create())
            .client(httpClient.build());


public class Trader implements Serializable {
    private String id;
    private long last_iteration_time;
   private double last_bnc_btx_diff_entrance_percent;
}

改造接口方法:

import kotlinx.coroutines.Deferred
import com.myproject.model.Trader
import retrofit2.Response
import retrofit2.http.GET
import retrofit2.http.Path
import retrofit2.http.Query


@GET("traders/json")
suspend fun getTraidersList(): Deferred<Response<List<Trader>>>

并使用它:

suspend fun getTraidersList(): TransportResponse = withContext(Dispatchers.IO) {
            val traderMonitorRestClient = RestClientFactory.createRestClient(TraderMonitorRestClient::class.java)
            val operrationDeferred: Deferred<Response<List<Trader>>> = traderMonitorRestClient.getTraidersList()
            executeAwaitOperation(operrationDeferred)
}

private suspend fun executeAwaitOperation(operation: Deferred<Response<*>>): TransportResponse = withContext(Dispatchers.IO) {
...
}

但是抛出异常:

06-17 17:27:58.634 W/top     (30820): type=1400 audit(0.0:139979963): avc: denied { search } for name="7" dev="proc" ino=9011 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:r:kernel:s0 tclass=dir permissive=0
06-17 17:27:58.982 E/AndroidRuntime(30688): FATAL EXCEPTION: main
06-17 17:27:58.982 E/AndroidRuntime(30688): Process: com.myproject.debug, PID: 30688
06-17 17:27:58.982 E/AndroidRuntime(30688): java.lang.RuntimeException: Unable to invoke no-args constructor for kotlinx.coroutines.Deferred<retrofit2.Response<java.util.List<com.myproject.model.Trader>>>. Registering an InstanceCreator with Gson for this type may fix this problem.
06-17 17:27:58.982 E/AndroidRuntime(30688):     at com.google.gson.internal.ConstructorConstructor$14.construct(ConstructorConstructor.java:228)
06-17 17:27:58.982 E/AndroidRuntime(30688):     at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:212)
06-17 17:27:58.982 E/AndroidRuntime(30688):     at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:37)
06-17 17:27:58.982 E/AndroidRuntime(30688):     at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:25)
06-17 17:27:58.982 E/AndroidRuntime(30688):     at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:225)
06-17 17:27:58.982 E/AndroidRuntime(30688):     at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:121)
06-17 17:27:58.982 E/AndroidRuntime(30688):     at okhttp3.RealCall$AsyncCall.execute(RealCall.java:206)
06-17 17:27:58.982 E/AndroidRuntime(30688):     at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
06-17 17:27:58.982 E/AndroidRuntime(30688):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
06-17 17:27:58.982 E/AndroidRuntime(30688):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
06-17 17:27:58.982 E/AndroidRuntime(30688):     at java.lang.Thread.run(Thread.java:818)
06-17 17:27:58.982 E/AndroidRuntime(30688): Caused by: java.lang.UnsupportedOperationException: Interface can't be instantiated! Interface name: kotlinx.coroutines.Deferred
06-17 17:27:58.982 E/AndroidRuntime(30688):     at com.google.gson.internal.UnsafeAllocator.assertInstantiable(UnsafeAllocator.java:117)
06-17 17:27:58.982 E/AndroidRuntime(30688):     at com.google.gson.internal.UnsafeAllocator$1.newInstance(UnsafeAllocator.java:49)
06-17 17:27:58.982 E/AndroidRuntime(30688):     at com.google.gson.internal.ConstructorConstructor$14.construct(ConstructorConstructor.java:225)
06-17 17:27:58.982 E/AndroidRuntime(30688):     ... 10 more
06-17 17:27:58.988 W/ActivityManager(  777):   Force finishing activity com.myproject.debug/com.myproject.ui.activity.TradersActivity

3 个答案:

答案 0 :(得分:8)

使用Deferred时,从Retrofit接口方法中删除暂停关键字。

答案 1 :(得分:3)

我有同样的问题。我从暂停函数调用接口中的函数,并且在接口中也将该函数称为暂停函数。解决方案是从界面的改装乐趣中删除暂停

例如:

之前:

interface ExampleInterface {
    @POST("someContextPath")
    suspend  fun postFeedback(
        @Body feedback: Feedback): Call<JsonObject>

}

之后:

interface ExampleInterface {
    @POST("someContextPath")
      fun postFeedback(
        @Body feedback: Feedback): Call<JsonObject>

}

答案 2 :(得分:0)

这是反序列化/序列化问题JSON <->对象。吉森只能为您做这件事。

您可以尝试为列表使用TypeAdapter。

您还可以尝试创建一个使用InstanceCreator反序列化的尝试,就像我必须使用包含LiveData的对象一样。

示例: https://futurestud.io/tutorials/gson-advanced-custom-instance-creator