Fragment未关联上下文,ArrayAdapter与AsyncTask中requireContext()报错求助
问题分析与解决方案
错误原因
- 错误创建Fragment实例:你在
onPostExecute里新建了LastSongs()实例,这个实例从未被添加到Activity中,既没有绑定View,也没有附着到上下文,完全不是当前显示的Fragment对象。 - 强引用导致的上下文失效:直接持有Fragment的强引用,当AsyncTask异步任务完成时,Fragment可能已经被销毁或与上下文分离,此时调用
requireContext()必然抛出异常。
方案一:修复现有AsyncTask代码
使用弱引用持有Fragment,同时在更新UI前检查Fragment的状态,避免无效操作:
class GetSongListAsync(fragment: LastSongs) : AsyncTask<Void, Void, Array<String>>() { // 用弱引用持有Fragment,避免内存泄漏 private val fragmentRef = WeakReference(fragment) override fun doInBackground(vararg params: Void): Array<String> { val url = URL("https://vivalaresistance.ru/radio/stuff/vlrradiobot.php?type=getPlaylist") val connection = url.openConnection() as HttpURLConnection connection.requestMethod = "GET" connection.connect() val songList = BufferedReader(InputStreamReader(connection.inputStream, "windows-1251")) connection.disconnect() return songList .readText() .replace("й", "й") .replace("Й", "Й") .split("\n").dropLast(1).toTypedArray() } override fun onPostExecute(result: Array<String>) { super.onPostExecute(result) // 获取当前Fragment实例,若已回收则直接返回 val fragment = fragmentRef.get() ?: return // 检查Fragment是否仍附着到Activity if (!fragment.isAdded) return // 使用当前Fragment的View获取ListView val list = fragment.view?.findViewById<ListView>(R.id.list) ?: return val arrayAdapter = ArrayAdapter(fragment.requireContext(), android.R.layout.simple_list_item_1, result) list.adapter = arrayAdapter } }
方案二:改用Coroutines(推荐)
AsyncTask已被Android官方废弃,使用协程更符合现代开发规范,且能自动跟随Fragment生命周期:
class LastSongs : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // 启动协程,自动在Fragment销毁时取消任务 lifecycleScope.launch { // 在IO线程执行网络请求 val songList = withContext(Dispatchers.IO) { val url = URL("https://vivalaresistance.ru/radio/stuff/vlrradiobot.php?type=getPlaylist") val connection = url.openConnection() as HttpURLConnection connection.requestMethod = "GET" connection.connect() val songList = BufferedReader(InputStreamReader(connection.inputStream, "windows-1251")) connection.disconnect() songList.readText() .replace("й", "й") .replace("Й", "Й") .split("\n").dropLast(1).toTypedArray() } // 回到主线程更新UI val list = view.findViewById<ListView>(R.id.list) val arrayAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_list_item_1, songList) list.adapter = arrayAdapter } } }
内容的提问来源于stack exchange,提问作者Mikhail K.
相关产品推荐
相关产品推荐

