Android Kotlin: как обновить recyclerView после асинхронного вызова?получение CalledFromWrongThreadException - PullRequest
0 голосов
/ 09 февраля 2019

Я пытаюсь выполнить асинхронный вызов, а затем обновить RecyclerView.Очень похоже на то, что изложено в этом вопросе: Обновление элемента RecyclerView + асинхронный сетевой вызов

Однако, когда я пытаюсь сделать это, я получаю эту ошибку: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

Вот мой код (основная проблема в функции setAlbums):

class AlbumActivity : AppCompatActivity() {

    protected lateinit var adapter: MyRecyclerViewAdapter
    protected lateinit var recyclerView: RecyclerView
    var animalNames = listOf("nothing")

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_album)

        recyclerView = findViewById<RecyclerView>(R.id.rvAnimals)
        recyclerView.layoutManager = LinearLayoutManager(this)
        adapter = MyRecyclerViewAdapter(this, animalNames)
        recyclerView.adapter = adapter

        urlCall("https://rss.itunes.apple.com/api/v1/us/apple-music/coming-soon/all/10/explicit.json")

    }

    private fun urlCall(url: String) {

        val client = OkHttpClient()
        val request = Request.Builder().url(url).build()

        client.newCall(request).enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {}
            override fun onResponse(call: Call, response: Response) = getJSON(response.body()?.string())
        })
    }

    fun getJSON(data: String?) {

        val gson = Gson()
        val allAlbums = ArrayList<Album>()

        val jsonResponse = JSONObject(data)
        val feed = jsonResponse.getJSONObject("feed")
        val albums = feed.getJSONArray("results")

        for (i in 0 until albums.length()) {
            val album = albums.getJSONObject(i)
            allAlbums.add(gson.fromJson(album.toString(), Album::class.java))
        }
        setAlbums(allAlbums)
    }


    fun setAlbums(albums: ArrayList<*>) {

        animalNames = listOf("sue", "betsie")
        adapter.notifyDataSetChanged() // This is where I am telling the adapter the data has changed
    }

    internal inner class Album {
        var artistName: String? = null
        var name: String? = null
    }
}

Кто-нибудь знает проблему, с которой я столкнулся?

Ответы [ 2 ]

0 голосов
/ 09 февраля 2019

Ваши Callback функции будут вызываться в фоновом потоке.Частично это связано с тем, что OkHttp не является библиотекой, специфичной для Android, поэтому он не имеет представления о главном потоке приложений Android.

Вам нужно будет что-то сделать, чтобы обновить пользовательский интерфейс в основном потоке приложений.Современные опции включают в себя:

  • Обновите Callback MutableLiveData, которое ваш пользовательский интерфейс наблюдает, так как тогда пользовательский интерфейс получит обновления в основном потоке приложения
  • Использовать существующие рецепты для с использованием OkHttp с RxJava
0 голосов
/ 09 февраля 2019

Вам нужно выполнить нужный код в главном потоке, например:

runOnUiThread(new Runnable() {

@Override
public void run() {
    //update your UI
    }
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...