我正在尝试使用异步方式从网络中获取数据,并将其填充到
我的代码:
recyclerview
中。我有一个名为 loadData()
的函数,它在 onCreateView()
中被调用,首先使加载指示器可见,然后调用挂起函数来加载数据,最后尝试通知视图适配器来更新。但是,在这一点上,我遇到了以下异常:
这让我感到惊讶,因为我的理解是只有我的android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
get_top_books()
函数是在不同的线程上被调用的,并且之前当我显示加载指示器时,我显然在正确的线程上。那么为什么会引发此运行时异常呢?我的代码:
class DiscoverFragment: Fragment() {
lateinit var loadingIndicator: TextView
lateinit var viewAdapter: ViewAdapter
var books = Books(arrayOf<String>("no books"), arrayOf<String>("no books"), arrayOf<String>("no books"))
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val viewFrame = layoutInflater?.inflate(R.layout.fragment_discover, container, false)
val viewManager = GridLayoutManager(viewFrame!!.context, 2)
viewAdapter = ViewAdapter(books)
loadingIndicator = viewFrame.findViewById<TextView>(R.id.loading_indicator)
val pxSpacing = (viewFrame.context.resources.displayMetrics.density * 8f + .5f).toInt()
val recyclerView = viewFrame.findViewById<RecyclerView>(R.id.recycler).apply {
setHasFixedSize(true)
layoutManager = viewManager
adapter = viewAdapter
addItemDecoration(RecyclerViewDecorationSpacer(pxSpacing, 2))
}
loadData()
return viewFrame
}
fun loadData() = CoroutineScope(Dispatchers.Default).launch {
loadingIndicator.visibility = View.VISIBLE
val task = async(Dispatchers.IO) {
get_top_books()
}
books = task.await()
viewAdapter.notifyDataSetChanged()
loadingIndicator.visibility = View.INVISIBLE
}
}
loadData()
函数中使用Dispatchers.Main
。 - y.allamwithContext(Dispatchers.Main)
? - EpicPandaForceGlobalScope.launch(Dispatchers.Default)
代替CoroutineScope(Dispatchers.Default).launch
。 - Dominic Fischerbooks = withContext(Dispatchers.IO) { get_top_books() }
,因为你不需要并发。 - Dominic Fischer