如何防止 onCreate 在 doAsync 完成之前返回结果
How to prevent onCreate from returning results before doAsync Completes
我在这里需要一些帮助(我是一名新程序员)。我正在用 Kotlin 编写一个应用程序,它要求我根据 GPS 位置找到当地的餐馆。找到它们后,我必须 return 将它们提供给用户。我正在处理的特定部分(我已完成地图视图)是餐厅特定详细信息的列表视图。
我遇到的问题 运行 是我的 doAsync 任务没有在 onCreateView(是的,它在片段中)return 视图之前完成。因此,视图是空白的。我试图让线程休眠,但它暂停了一切,包括异步任务。无论我做什么,当视图被 returned 时,restaurantList.size 始终为 0,视图始终为空白。我可以在日志中看到,列表之前的视图 returns 已填充。我已经为此工作了 2 周了。有人可以帮我吗?
这是我的 onCreateView 代码:
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val root = inflater.inflate(R.layout.fragment_list, container, false)
fusedLocationClient = LocationServices.getFusedLocationProviderClient(requireActivity())
if (checkPermission(Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION)) {
fusedLocationClient?.lastLocation?.addOnSuccessListener(requireActivity()) { location: Location? ->
if (location == null) {
// TODO, handle it
} else location.apply {
var long = location.longitude
var lat = location.latitude
// Handle location object
var type = "restaurant"
var url = getUrl(lat, long, type)
doAsync {
var googlePlacesData = (URL(url).readText())
onComplete {
val parser = DataParser()
nearbyPlaceList = parser.parse(googlePlacesData)
for (i in nearbyPlaceList.indices) {
val googlePlace = nearbyPlaceList[i]
placeName = googlePlace["place_name"]!!
vicinity = googlePlace["vicinity"]
id = googlePlace["place_id"]
val detailURL = StringBuilder("https://maps.googleapis.com/maps/api/place/details/json?")
detailURL.append("place_id=" + id)
detailURL.append("&key=" + "KEY_GOES_HERE")
doAsync {
var detailData = (URL(detailURL.toString()).readText())
onComplete {
val jsonObject: JSONObject
val jsonObject2: JSONObject
jsonObject = JSONObject(detailData)
jsonObject2 = jsonObject.getJSONObject("result")
if (!jsonObject2.isNull("name")) {
placeName = jsonObject2.getString("name")
}
if (!jsonObject2.isNull("place_id")) {
placeId = jsonObject2.getString("place_id")
}
if (!jsonObject2.isNull("formatted_address")) {
address = jsonObject2.getString("formatted_address")
}
if (!jsonObject2.isNull("formatted_phone_number")) {
phone = jsonObject2.getString("formatted_phone_number")
}
if (!jsonObject2.isNull("website")) {
website = jsonObject2.getString("website")
}
if (!jsonObject2.isNull("rating")) {
rating = jsonObject2.getDouble("rating")
}
if (bmImg == null) {
var jsonPhotosArray: JSONArray? = null
if (jsonObject2.has("photos")) {
jsonPhotosArray = jsonObject2.getJSONArray("photos")
val obj = jsonPhotosArray.getJSONObject(0)
photoReference = obj.getString("photo_reference")
val photoURL =
StringBuilder("https://maps.googleapis.com/maps/api/place/photo?")
photoURL.append("maxwidth=500")
photoURL.append("&maxheight=500")
photoURL.append("&key=" + "KEY_GOES_HERE")
photoURL.append("&photoreference=" + photoReference)
doAsync {
ImageUrl = URL(photoURL.toString())
val conn =
ImageUrl.openConnection() as HttpURLConnection
conn.setDoInput(true)
conn.connect()
var `is` = conn.getInputStream()
val options = BitmapFactory.Options()
options.inPreferredConfig = Bitmap.Config.RGB_565
bmImg =
BitmapFactory.decodeStream(`is`, null, options)!!
onComplete {
var style = "Restaurant"
var openTil = "7 p.m."
var distance = "0.0"
var empsGoing = "2"
restaurantList.add(ListViewModel(placeName,style,address, openTil, distance, empsGoing, rating, phone))
Log.d("Log", "List Total = " + restaurantList.size)
}
}
}
}
}
}
}
}
}
}
}
Toast.makeText(requireContext(), "Listing Nearby Restaurants", Toast.LENGTH_SHORT).show()
}
Log.d("Log", "List Total End= " + restaurantList.size)
val recyclerview = root.findViewById(R.id.rvList) as RecyclerView
recyclerview.layoutManager = LinearLayoutManager(requireActivity())
recyclerview.adapter = RecyclerAdapter(restaurantList, requireContext())
return root
}
这是我得到的日志输出:
2020-07-25 07:39:47.354 17576-17576/com.mark.lunchappredesign D/Log: Inside onCreate
2020-07-25 07:39:53.415 17576-17576/com.mark.lunchappredesign D/Log: List Total End= 0
2020-07-25 07:39:53.494 17576-17576/com.mark.lunchappredesign D/Log: ListFragment - url = https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=39.812755,-85.7664&radius=5000&type=restaurant&sensor=true&key=KEY_GOES_HERE
2020-07-25 07:39:53.992 17576-17576/com.mark.lunchappredesign D/Log: DataParser - jsonobject ={"business_status":"OPERATIONAL","geometry":{"location":{"lat":39.80146370000001,"lng":-85.7692799},"viewport":{"northeast":{"lat":39.80274508029151,"lng":-85.7679299197085},"southwest":{"lat":39.80004711970851,"lng":-85.7706278802915}}},"icon":"https:\/\/maps.gstatic.com\/mapfiles\/place_api\/icons\/restaurant-71.png","id":"297878a9f9b57ecb7d7c00c3a695b30ec908c5d4","name":"Subway","opening_hours":{"open_now":false},"photos":[{"height":2988,"html_attributions":["<a href=\"https:\/\/maps.google.com\/maps\/contrib\/116980312202159126535\">Janet Williams<\/a>"],"photo_reference":"CmRaAAAAVQBC5037LqGuRj5bmi0IJg3mYRaZZGWTO--YmFq6iMTRDxWQTEyMILNhI1pjY-T1Ma8Cb_HxvFQc31_Nt-oQv-rOy61APaP5Wytcog
...
...
2020-07-25 07:39:54.918 17576-17576/com.mark.lunchappredesign D/Log: List Total = 1
2020-07-25 07:39:54.931 17576-17576/com.mark.lunchappredesign D/Log: List Total = 2
2020-07-25 07:39:54.942 17576-17576/com.mark.lunchappredesign D/Log: List Total = 3
2020-07-25 07:39:55.022 17576-17576/com.mark.lunchappredesign D/Log: List Total = 4
2020-07-25 07:39:55.034 17576-17576/com.mark.lunchappredesign D/Log: List Total = 5
2020-07-25 07:39:55.034 17576-17576/com.mark.lunchappredesign D/Log: List Total = 6
2020-07-25 07:39:55.083 17576-17576/com.mark.lunchappredesign D/Log: List Total = 7
2020-07-25 07:39:55.091 17576-17576/com.mark.lunchappredesign D/Log: List Total = 8
2020-07-25 07:39:55.126 17576-17576/com.mark.lunchappredesign D/Log: List Total = 9
2020-07-25 07:39:55.131 17576-17576/com.mark.lunchappredesign D/Log: List Total = 10
2020-07-25 07:39:55.172 17576-17576/com.mark.lunchappredesign D/Log: List Total = 11
2020-07-25 07:39:55.183 17576-17576/com.mark.lunchappredesign D/Log: List Total = 12
2020-07-25 07:39:55.194 17576-17576/com.mark.lunchappredesign D/Log: List Total = 13
2020-07-25 07:39:55.203 17576-17576/com.mark.lunchappredesign D/Log: List Total = 14
2020-07-25 07:39:55.273 17576-17576/com.mark.lunchappredesign D/Log: List Total = 15
2020-07-25 07:39:55.278 17576-17576/com.mark.lunchappredesign D/Log: List Total = 16
2020-07-25 07:39:55.310 17576-17576/com.mark.lunchappredesign D/Log: List Total = 17
2020-07-25 07:39:55.410 17576-17576/com.mark.lunchappredesign D/Log: List Total = 18
2020-07-25 07:39:55.611 17576-17576/com.mark.lunchappredesign D/Log: List Total = 19
将这部分代码移到 onComplete
块中:
Log.d("Log", "List Total End= " + restaurantList.size)
val recyclerview = root.findViewById(R.id.rvList) as RecyclerView
recyclerview.layoutManager = LinearLayoutManager(requireActivity())
recyclerview.adapter = RecyclerAdapter(restaurantList, requireContext())
无论如何,代码显然不是完美的,还有很多需要改进的地方。请注意,无论如何,当您添加 Fragment
时,它不一定具有远程数据。通常在创建 Fragment
时调用 API,然后在 onComplete
中,您可以使用数据填充视图。
所以,我终于弄明白了!问题出在“添加”语句的位置!因为我只为每个餐厅下载 1 张图像,所以我有一个 if 语句来限制该部分代码 (if (bmImg == null))
因此,add 语句只执行了一次。 . .对于最后添加的餐厅!
感谢大家的帮助,感谢大家的关注!
我在这里需要一些帮助(我是一名新程序员)。我正在用 Kotlin 编写一个应用程序,它要求我根据 GPS 位置找到当地的餐馆。找到它们后,我必须 return 将它们提供给用户。我正在处理的特定部分(我已完成地图视图)是餐厅特定详细信息的列表视图。
我遇到的问题 运行 是我的 doAsync 任务没有在 onCreateView(是的,它在片段中)return 视图之前完成。因此,视图是空白的。我试图让线程休眠,但它暂停了一切,包括异步任务。无论我做什么,当视图被 returned 时,restaurantList.size 始终为 0,视图始终为空白。我可以在日志中看到,列表之前的视图 returns 已填充。我已经为此工作了 2 周了。有人可以帮我吗?
这是我的 onCreateView 代码:
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val root = inflater.inflate(R.layout.fragment_list, container, false)
fusedLocationClient = LocationServices.getFusedLocationProviderClient(requireActivity())
if (checkPermission(Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION)) {
fusedLocationClient?.lastLocation?.addOnSuccessListener(requireActivity()) { location: Location? ->
if (location == null) {
// TODO, handle it
} else location.apply {
var long = location.longitude
var lat = location.latitude
// Handle location object
var type = "restaurant"
var url = getUrl(lat, long, type)
doAsync {
var googlePlacesData = (URL(url).readText())
onComplete {
val parser = DataParser()
nearbyPlaceList = parser.parse(googlePlacesData)
for (i in nearbyPlaceList.indices) {
val googlePlace = nearbyPlaceList[i]
placeName = googlePlace["place_name"]!!
vicinity = googlePlace["vicinity"]
id = googlePlace["place_id"]
val detailURL = StringBuilder("https://maps.googleapis.com/maps/api/place/details/json?")
detailURL.append("place_id=" + id)
detailURL.append("&key=" + "KEY_GOES_HERE")
doAsync {
var detailData = (URL(detailURL.toString()).readText())
onComplete {
val jsonObject: JSONObject
val jsonObject2: JSONObject
jsonObject = JSONObject(detailData)
jsonObject2 = jsonObject.getJSONObject("result")
if (!jsonObject2.isNull("name")) {
placeName = jsonObject2.getString("name")
}
if (!jsonObject2.isNull("place_id")) {
placeId = jsonObject2.getString("place_id")
}
if (!jsonObject2.isNull("formatted_address")) {
address = jsonObject2.getString("formatted_address")
}
if (!jsonObject2.isNull("formatted_phone_number")) {
phone = jsonObject2.getString("formatted_phone_number")
}
if (!jsonObject2.isNull("website")) {
website = jsonObject2.getString("website")
}
if (!jsonObject2.isNull("rating")) {
rating = jsonObject2.getDouble("rating")
}
if (bmImg == null) {
var jsonPhotosArray: JSONArray? = null
if (jsonObject2.has("photos")) {
jsonPhotosArray = jsonObject2.getJSONArray("photos")
val obj = jsonPhotosArray.getJSONObject(0)
photoReference = obj.getString("photo_reference")
val photoURL =
StringBuilder("https://maps.googleapis.com/maps/api/place/photo?")
photoURL.append("maxwidth=500")
photoURL.append("&maxheight=500")
photoURL.append("&key=" + "KEY_GOES_HERE")
photoURL.append("&photoreference=" + photoReference)
doAsync {
ImageUrl = URL(photoURL.toString())
val conn =
ImageUrl.openConnection() as HttpURLConnection
conn.setDoInput(true)
conn.connect()
var `is` = conn.getInputStream()
val options = BitmapFactory.Options()
options.inPreferredConfig = Bitmap.Config.RGB_565
bmImg =
BitmapFactory.decodeStream(`is`, null, options)!!
onComplete {
var style = "Restaurant"
var openTil = "7 p.m."
var distance = "0.0"
var empsGoing = "2"
restaurantList.add(ListViewModel(placeName,style,address, openTil, distance, empsGoing, rating, phone))
Log.d("Log", "List Total = " + restaurantList.size)
}
}
}
}
}
}
}
}
}
}
}
Toast.makeText(requireContext(), "Listing Nearby Restaurants", Toast.LENGTH_SHORT).show()
}
Log.d("Log", "List Total End= " + restaurantList.size)
val recyclerview = root.findViewById(R.id.rvList) as RecyclerView
recyclerview.layoutManager = LinearLayoutManager(requireActivity())
recyclerview.adapter = RecyclerAdapter(restaurantList, requireContext())
return root
}
这是我得到的日志输出:
2020-07-25 07:39:47.354 17576-17576/com.mark.lunchappredesign D/Log: Inside onCreate
2020-07-25 07:39:53.415 17576-17576/com.mark.lunchappredesign D/Log: List Total End= 0
2020-07-25 07:39:53.494 17576-17576/com.mark.lunchappredesign D/Log: ListFragment - url = https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=39.812755,-85.7664&radius=5000&type=restaurant&sensor=true&key=KEY_GOES_HERE
2020-07-25 07:39:53.992 17576-17576/com.mark.lunchappredesign D/Log: DataParser - jsonobject ={"business_status":"OPERATIONAL","geometry":{"location":{"lat":39.80146370000001,"lng":-85.7692799},"viewport":{"northeast":{"lat":39.80274508029151,"lng":-85.7679299197085},"southwest":{"lat":39.80004711970851,"lng":-85.7706278802915}}},"icon":"https:\/\/maps.gstatic.com\/mapfiles\/place_api\/icons\/restaurant-71.png","id":"297878a9f9b57ecb7d7c00c3a695b30ec908c5d4","name":"Subway","opening_hours":{"open_now":false},"photos":[{"height":2988,"html_attributions":["<a href=\"https:\/\/maps.google.com\/maps\/contrib\/116980312202159126535\">Janet Williams<\/a>"],"photo_reference":"CmRaAAAAVQBC5037LqGuRj5bmi0IJg3mYRaZZGWTO--YmFq6iMTRDxWQTEyMILNhI1pjY-T1Ma8Cb_HxvFQc31_Nt-oQv-rOy61APaP5Wytcog
...
...
2020-07-25 07:39:54.918 17576-17576/com.mark.lunchappredesign D/Log: List Total = 1
2020-07-25 07:39:54.931 17576-17576/com.mark.lunchappredesign D/Log: List Total = 2
2020-07-25 07:39:54.942 17576-17576/com.mark.lunchappredesign D/Log: List Total = 3
2020-07-25 07:39:55.022 17576-17576/com.mark.lunchappredesign D/Log: List Total = 4
2020-07-25 07:39:55.034 17576-17576/com.mark.lunchappredesign D/Log: List Total = 5
2020-07-25 07:39:55.034 17576-17576/com.mark.lunchappredesign D/Log: List Total = 6
2020-07-25 07:39:55.083 17576-17576/com.mark.lunchappredesign D/Log: List Total = 7
2020-07-25 07:39:55.091 17576-17576/com.mark.lunchappredesign D/Log: List Total = 8
2020-07-25 07:39:55.126 17576-17576/com.mark.lunchappredesign D/Log: List Total = 9
2020-07-25 07:39:55.131 17576-17576/com.mark.lunchappredesign D/Log: List Total = 10
2020-07-25 07:39:55.172 17576-17576/com.mark.lunchappredesign D/Log: List Total = 11
2020-07-25 07:39:55.183 17576-17576/com.mark.lunchappredesign D/Log: List Total = 12
2020-07-25 07:39:55.194 17576-17576/com.mark.lunchappredesign D/Log: List Total = 13
2020-07-25 07:39:55.203 17576-17576/com.mark.lunchappredesign D/Log: List Total = 14
2020-07-25 07:39:55.273 17576-17576/com.mark.lunchappredesign D/Log: List Total = 15
2020-07-25 07:39:55.278 17576-17576/com.mark.lunchappredesign D/Log: List Total = 16
2020-07-25 07:39:55.310 17576-17576/com.mark.lunchappredesign D/Log: List Total = 17
2020-07-25 07:39:55.410 17576-17576/com.mark.lunchappredesign D/Log: List Total = 18
2020-07-25 07:39:55.611 17576-17576/com.mark.lunchappredesign D/Log: List Total = 19
将这部分代码移到 onComplete
块中:
Log.d("Log", "List Total End= " + restaurantList.size)
val recyclerview = root.findViewById(R.id.rvList) as RecyclerView
recyclerview.layoutManager = LinearLayoutManager(requireActivity())
recyclerview.adapter = RecyclerAdapter(restaurantList, requireContext())
无论如何,代码显然不是完美的,还有很多需要改进的地方。请注意,无论如何,当您添加 Fragment
时,它不一定具有远程数据。通常在创建 Fragment
时调用 API,然后在 onComplete
中,您可以使用数据填充视图。
所以,我终于弄明白了!问题出在“添加”语句的位置!因为我只为每个餐厅下载 1 张图像,所以我有一个 if 语句来限制该部分代码 (if (bmImg == null))
因此,add 语句只执行了一次。 . .对于最后添加的餐厅!
感谢大家的帮助,感谢大家的关注!