程序问答   发布时间:2022-06-02  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了将 android.content.Context 传递给挂起的函数会导致 android.os.NetworkOnMainThreadException大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决将 android.content.Context 传递给挂起的函数会导致 android.os.NetworkOnMainThreadException?

开发过程中遇到将 android.content.Context 传递给挂起的函数会导致 android.os.NetworkOnMainThreadException的问题如何解决?下面主要结合日常开发的经验,给出你关于将 android.content.Context 传递给挂起的函数会导致 android.os.NetworkOnMainThreadException的解决方法建议,希望对你解决将 android.content.Context 传递给挂起的函数会导致 android.os.NetworkOnMainThreadException有所启发或帮助;

我有一个挂起的函数,它通过网络调用来获取一些数据并返回它。我正在使用 Volley。

class PokeClIEnt {
suspend fun getPokemonData(pokemonname: String,context: Context) = suspendCoroutIne<Pokemon> { cont ->
    val queue = Volley.newrequestQueue(context)
    val request = url.plus(pokemonName)
    // some skipped code here
}

我在我的活动中这样调用它:

GlobalScope.launch {
        val pokeResult = pokeClIEnt.getPokemonData(nameToSearch,applicationContext)
        pokemonList.add(pokeResult)
        pokemonAdapter.notifyItemInserted(pokemonList.size - 1)
    }

然后我收到如下错误:androID.os.networkonmainthreadException

我怀疑这可能是因为我正在从 MainActivity 传递上下文,这不正确。这里的替代方案是什么?

谢谢,

安卓新手

更新:

将 android.content.Context 传递给挂起的函数会导致 android.os.NetworkOnMainThreadException

class MainActivity : AppCompatActivity() {
overrIDe fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceStatE)
    setContentVIEw(R.layout.activity_main)

    val pokeClIEnt = PokeClIEnt()
    var pokemonList = mutablelistof<Pokemon>()

    val pokemonAdapter = PokemonRvAdapter(pokemonList)
    val pokemonRv = findVIEwByID<RecyclerVIEw>(R.ID.rv_pokemon)
    pokemonRv.adapter = pokemonAdapter
    pokemonRv.layoutManager = linearlayoutmanager(this)

    val searchbutton = findVIEwByID<button>(R.ID.search_btn)
    searchbutton.setonClickListener {
        val toast = Toast.makeText(applicationContext,"Loading poke data",Toast.LENGTH_SHORT)
        toast.show()

        val nameToSearch = findVIEwByID<EditText>(R.ID.search_pokemon_txt).text.toString().lowercase()

        GlobalScope.launch(dispatchers.IO) {
            val pokeResult = pokeClIEnt.getPokemonData(nameToSearch,applicationContext)
            pokemonList.add(pokeResult)
            pokemonAdapter.notifyItemInserted(pokemonList.size - 1)
        }
    }
}
}

PokeClIEnt:

const val url = "https://pokeAPI.co/API/v2/pokemon/"

class PokeClIEnt {
suspend fun getPokemonData(pokemonname: String,context: Context) = suspendCoroutIne<Pokemon> { cont ->
    val queue = Volley.newrequestQueue(context)
    val request = url.plus(pokemonName)

        val Stringrequest = Stringrequest(request.Method.GET,request,Response.Listener<String> { response ->
            val jObj = JsONObject(responsE)
            val imgurl = jObj
                .getJsONObject("Sprites")
                .getJsONObject("other")
                .getJsONObject("official-artwork")
                .getString("front_default")

            val inputStream = URL(imgurl).openStream()
            /* call conTinuation.resume and pass your object */
            cont.resume(Pokemon(name = jObj.getString("name"),image = BitmapFactory.decodeStream(inputStream)))
        },Response.ErrorListener { err ->
            cont.resumeWithException(err)
        })

        queue.add(Stringrequest)
}
}

解决方法

根据 CommonsWare 评论,似乎 Dispatchers.IO 是您在这里所缺少的。准确地说,它应该是这样的

GlobalScope.launch(Dispatchers.IO) {
    val pokeResult = pokeClient.getPokemonData(nameToSearch,applicationContext)
    pokemonList.add(pokeResult)
    pokemonAdapter.notifyItemInserted(pokemonList.size - 1)
}

   GlobalScope.launch {

      withContext(Dispatchers.IO) {
      val pokeResult = pokeClient.getPokemonData(nameToSearch,applicationContext)
      pokemonList.add(pokeResult)
      pokemonAdapter.notifyItemInserted(pokemonList.size - 1)
  }
}
,

然我对 kotlin 完全不了解,但就我而言,当您在主线程上执行 Internet 相关操作(例如,从站点加载数据) 或您没有执行此操作时,会发生此错误在清单文件中声明了互联网权限。相反,您应该创建新线程并在那里执行操作。如果你不介意在这里添加 java 代码是一个片段

  class getData implements Runnable{
        @Override
        public void run() {
           //Do work over here such as loading date from url

            runOnUiThread(new Runnable() {
                @Override
                public void run() {

                    //To update ui put code inside here

                }
            });
        }
    }

在主方法中使用这个

        Thread thread = new Thread(new getData());//use class name
        thread.start();//To start execution

大佬总结

以上是大佬教程为你收集整理的将 android.content.Context 传递给挂起的函数会导致 android.os.NetworkOnMainThreadException全部内容,希望文章能够帮你解决将 android.content.Context 传递给挂起的函数会导致 android.os.NetworkOnMainThreadException所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。