简体   繁体   中英

E/AndroidRuntime: FATAL EXCEPTION: main and Coroutine, Retrofit2

I just started learning kotlin and my first app use Retrofit2 and Coroutine, but there is problem. I have some error, but by Coroutine the stack trace is very poor in informations. Maybe someone will find a mistake or knows hot to make the stack trace more informative.

ApiService:

const val API_KEY = "Bcae2032bb596c73b10bdab625c037da"

interface CurrencyApi {

//https://api.currencystack.io/currency?base=USD&target=EUR&apikey=Bcae2032bb596c73b10bdab625c037da

@GET("currency")
fun getCurrentCurrency(
    @Query("base") base: String,
    @Query("target") target: String
): Deferred<Currency>

companion object {
    operator fun invoke(): CurrencyApi {
        val requestInterceptor = Interceptor { chain ->

            val url = chain.request()
                .url()
                .newBuilder()
                .addQueryParameter("key", API_KEY)
                .build()
            val request = chain.request()
                .newBuilder()
                .url(url)
                .build()

            return@Interceptor chain.proceed(request)
        }

        val okHttpClient = OkHttpClient.Builder()
            .addInterceptor(requestInterceptor)
            .build()

        return Retrofit.Builder()
            .client(okHttpClient)
            .baseUrl("https://api.currencystack.io/")
            .addCallAdapterFactory(CoroutineCallAdapterFactory())
            .addConverterFactory(GsonConverterFactory.create())
            .build()
            .create(CurrencyApi::class.java)
    }
}

Activity:

 class MainActivity : AppCompatActivity(), AdapterView.OnItemSelectedListener {


override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val binding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
    val model = ViewModelProviders.of(this).get(MainViewModel::class.java)

    val apiService = CurrencyApi()

    GlobalScope.launch(Dispatchers.Main) {
        val currency = apiService.getCurrentCurrency("PLN", "EUR").await()
        return@launch try {
            text_view_test.text = currency.toString()
        } catch (e: Exception) {

        }
    }

Logcat:

E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.daniellachacz.currencyconverter, PID: 10924 retrofit2.HttpException: HTTP 400 at com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory$BodyCallAdapter$adapt$2.onResponse(CoroutineCallAdapterFactory.kt:104) at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:123) at okhttp3.RealCall$AsyncCall.execute(RealCall.java:153) at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) at java.lang.Thread.run(Thread.java:818)

You receive server error 400 Bad Request response. This status code indicates that the server could not understand the request due to invalid syntax. Try to debug or put some logs and see what you are really sending to the server. I think the good place to debug is in the implementation of Interceptor interface.

As @Sergey said, it is a server error.

In my case it couldn't be caught by an API and the server wrote: An internal server error occurred. (code 500) instead of a JSON.

@GET(currency)替换为@GET(currency.json)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM