【问题标题】:Kotlin Coroutines, retrofit-2.6.1, Network response nullKotlin Coroutines,retrofit-2.6.1,网络响应 null
【发布时间】:2020-02-24 14:57:02
【问题描述】:

我正在学习 reso-coder Weather app 教程。大多数事情随着时间的推移而改变,apixu天气网站也是如此。
现在是Retrofit 2.6.1 的时间,这意味着kotlin coroutines
问题是我在网络响应中得到所有 Null
我已经使用 SerializedName 浏览了所有数据类,一切似乎都很好,仍然无法解决问题..
顺便说一句,我现在没有使用ViewModel,只是直接希望进入片段 textView

interface ApixuWeatherApiService {


 @GET("current")
    suspend fun getCurrentWeather(
        @Query("query") location: String,
        @Query("lang") languageCode: String = "en"
    ): CurrentWeatherResponse

    //to handle this above interface we need companion object

    companion object WeatherAPis {
        private val requestInterceptor = Interceptor { chain ->
            val url = chain.request()
                .url().newBuilder().addQueryParameter("access_key", API_KEY)
                .build()

            val request = chain.request().newBuilder().url(url).build()
            chain.proceed(request)
        }
        private val okHTTPClient = OkHttpClient.Builder().addInterceptor(requestInterceptor).build()
        private fun retroFit(): Retrofit = Retrofit
            .Builder()
            .client(okHTTPClient)
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .build()

        val weatherApi: ApixuWeatherApiService =
            retroFit().create(ApixuWeatherApiService::class.java)
    }
}

片段类


class CurrentWeatherFragment : Fragment() {


    private lateinit var viewModel: CurrentWeatherViewModel

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.current_weather_fragment, container, false)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        viewModel = ViewModelProviders.of(this).get(CurrentWeatherViewModel::class.java)
        CoroutineScope(IO).launch {
            widCOntext()
        }

    }


    private suspend fun widCOntext() {
        val apiService = ApixuWeatherApiService.weatherApi
            withContext(Main) {
                val currentWeatherResponse =
                    withContext(IO) {
                        apiService.getCurrentWeather(
                            "London"
                        )
                    }
                txtView.text = currentWeatherResponse.toString()
            }

    }
}

我已经使用插件将 JSON 转换为 kotlin 文件以获取这些
四个数据类
当前

data class Current(
    @SerializedName("observation_time")
    val observationTime: String,
    val temperature: Int,
    @SerializedName("weather_code")
    val weatherCode: Int,
    @SerializedName("weather_icons")
    val weatherIcons: List<String>,
    @SerializedName("weather_descriptions")
    val weatherDescriptions: List<String>,
    @SerializedName("wind_speed")
    val windSpeed: Int,
    @SerializedName("wind_degree")
    val windDegree: Int,
    @SerializedName("wind_dir")
    val windDir: String,
    val pressure: Int,
    val precip: Int,
    val humidity: Int,
    val cloudcover: Int,
    val feelslike: Int,
    @SerializedName("uv_index")
    val uvIndex: Int,
    val visibility: Int,
    @SerializedName("is_day")
    val isDay: String
)

CurrentWeatherResponse

data class CurrentWeatherResponse(
    val request: Request,
    val location: Location,
    val current: Current
)

位置

data class Location(
    val name: String,
    val country: String,
    val region: String,
    val lat: String,
    val lon: String,
    @SerializedName("timezone_id")
    val timezoneId: String,
    val localtime: String,
    @SerializedName("localtime_epoch")
    val localtimeEpoch: Int,
    @SerializedName("utc_offset")
    val utcOffset: String
)

请求

data class Request(
    val type: String,
    val query: String,
    val language: String,
    val unit: String
)

【问题讨论】:

  • 所以它既不抛出异常也不返回结果?您是否尝试过将返回类型从 CurrentWeatherResponse 更改为 Response
  • 不。我的 textView 只是显示为 null,它是在 textView 上写的 null。更改为 Response 后,它显示了一些奇怪的输出,例如 protocol=h2, code=200,message, url= websiteurl
  • 您可以尝试打印response.body() 吗?另外,你的CurrentWeatherResponse 班级是什么样子的?
  • @r2rek 是的,我尝试打印 response.body() 并得到完全相同的 null 响应。在这里,debug: CurrentWeatherResponse(request=null, location=null, current=null) 这就是我在 textView 中得到的。顺便说一句,我已经更新了我的问题并添加了data classes
  • 尝试添加一个httpInterceptor并粘贴请求的结果github.com/square/okhttp/tree/master/okhttp-logging-interceptor

标签: android-studio request kotlin-coroutines retrofit2.6


【解决方案1】:

问题已解决:我希望这能帮助某人
这是我所做的
每当我卡在某个地方时,我都会创建新项目并尝试处理那个特定的事情。
现在我在这里做了什么,我认为解决了我的问题。
我使用了单例模式,我制作了 ApiService 接口 的单例实例,在 singleton 之前它显示响应 200 但输出也是 null 并且现在只需制作 singleton 它就解决了我的问题,现在我得到了想要的输出
这是代码:

object RetrofitRequest {

    private val interceptor = Interceptor {chain ->
        val url = chain.request()
            .url()
            .newBuilder()
            .addQueryParameter("access_key/key", yourApiKey)
            .build()

        val request = chain.request().newBuilder().url(url).build()

        return@Interceptor chain.proceed(request)
    }

    private val okHttpClient = OkHttpClient
        .Builder()
        .addInterceptor(interceptor)
        .build()

    @Volatile
    private var instance : ApiService? = null
    fun getInstance() : ApiService = instance ?: synchronized(this) {
        instance ?: fullResponse().also {
            instance = it
        }
    }

    private fun retrofitBuild() : Retrofit =
        Retrofit.Builder()
           .client(okHttpClient)
           .baseUrl(BASE_URL)
           .addConverterFactory(GsonConverterFactory.create())
            .build()


    private fun fullResponse(): ApiService {
        return retrofitBuild().create(ApiService::class.java)
    }

}

具体来说这是我要说的部分

@Volatile
    private var instance : ApiService? = null
    fun getInstance() : ApiService = instance ?: synchronized(this) {
        instance ?: fullResponse().also {
            instance = it
        }
    }

现在我认为这里发生了什么:
Singleton 之前响应成功,但 instance 对其他线程不可见。这就是为什么它是 null。当我使用 coroutines 时,它可能从不同的线程运行,在使 singleton @volatile 使得 singleton 对所有线程可见之后。当程序尝试从不同的线程运行时,@Volatile 具有访问所有线程的能力,这使得程序在没有 null 的情况下成功执行

【讨论】:

    猜你喜欢
    • 2020-04-25
    • 2019-10-05
    • 2020-01-16
    • 2020-10-26
    • 1970-01-01
    • 2021-10-02
    • 1970-01-01
    • 2018-08-01
    相关资源
    最近更新 更多