我一直在return place
上拿到一个NullPointerException。
当我调试应用程序时,代码跳过了onFailure()
和onResponse()
方法。
以前,这是有效的,但我将其重构为当前的类。
class Repository private constructor() {
private val baseUrl: String = "http://api.openweathermap.org/"
val client = OkHttpClient.Builder()
.addInterceptor(HttpLoggingInterceptor()
.setLevel(HttpLoggingInterceptor.Level.BODY))
.build()
val retrofit = Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(MoshiConverterFactory.create())
.client(client)
.build()
val networkApi = retrofit.create(NetworkApi::class.java)
private object Holder { val INSTANCE = Repository() }
companion object {
val instance: Repository by lazy { Holder.INSTANCE }
}
fun fetchWeatherData(placeName: String): Place {
var place: Place? = null
val call: Call<Place> = networkApi.getPlaceWeather(placeName)
call.enqueue(object : Callback<Place> {
override fun onFailure(call: Call<Place>?, t: Throwable?) {
println(t?.message)
}
override fun onResponse(call: Call<Place>?, response: Response<Place>?) {
if (response != null && response.isSuccessful && response.body() != null) {
place = response.body() as Place
println(place.toString())
}
}
})
return place!!
}
}
class MainPresenter(private val view: MainContract.View, val context: Context) : MainContract.Presenter {
val repository = Repository.instance
...
override fun updateListOfPlaces() {
var places = mutableListOf<Place>()
for (index in 0 until favPlaceStrings.size) {
places.add(repository.fetchWeatherData(favPlaceStrings.elementAt(index)))
}
view.showFavouritePlaces(places)
}
}
发布于 2018-07-09 20:35:07
你需要反转你的逻辑。您不能简单地从您等待的网络调用中“返回数据”
相反,循环遍历列表,发出请求,然后显示/更新视图
for (index in 0 until favPlaceStrings.size) {
val call: Call<Place> = networkApi.getPlaceWeather(favPlaceStrings.elementAt(index))
call.enqueue(object : Callback<Place> {
override fun onFailure(call: Call<Place>?, t: Throwable?) {
println(t?.message)
}
override fun onResponse(call: Call<Place>?, response: Response<Place>?) {
if (response != null && response.isSuccessful && response.body() != null) {
val place: Place = response.body() as Place
places.add(place) // move this list to a field
println(place.toString())
view.showFavouritePlaces(places) // this is fine that it's inside a loop
}
}
})
}
发布于 2018-07-09 20:25:53
使用retrofit的方式使其具有异步行为,这意味着onFailure
和onResponse
中的代码可能会在您有机会从fetchWeatherData
返回之前或之后运行。换句话说,你不能假设当你从fetchWeatherData
返回时place
会有一个值,这就是实际发生的情况,place
仍然是null
,调用!!
会导致空指针异常。
要解决此问题,您可以更改使用改进的方式以实现同步,或者使用像回调这样的方法。
就我个人而言,我更喜欢回调方法/反应流,这是你可以查看here的。
使代码同步很可能会导致其他问题,如主线程上的网络调用,这是不允许的,并使应用程序崩溃。
https://stackoverflow.com/questions/51242443
复制相似问题