Парсинг JSON с удалённого сервера (Kotlin)

Есть RecyclerView, в который парсится JSON с удалённого сервера.

UPD MainActivity.kt:

import android.annotation.SuppressLint
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
import java.io.IOException
import okhttp3.*

class MainActivity : AppCompatActivity() {

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

        val client = OkHttpClient()

        val list = ArrayList<ListItem>()

        val rcView = findViewById<RecyclerView>(R.id.rv_content)
        rcView.layoutManager = LinearLayoutManager(this)
        rcView.adapter = MyAdapter(list, this)
        rcView.hasFixedSize()

        val request: Request = Request.Builder()
            .url("http://some_link/api/")
            .build()

        client.newCall(request).enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                e.printStackTrace()
            }

            override fun onResponse(call: Call, response: Response) {
                val strResponse = response.body!!.string()
                try {
                    val episodeArray = JSONArray(strResponse)
                    for (i in 0 until episodeArray.length()) {
                        val episodeDetails = episodeArray.getJSONObject(i)
                        list.add(
                            ListItem(
                                episodeDetails.getString("pub_date"),
                                episodeDetails.getString("title"),
                                episodeDetails.getString("description"),
                                episodeDetails.getString("youtube_link"),
                            )
                        )
                    }
                    rcView.adapter?.notifyDataSetChanged()
                } catch (e: JSONException) {
                    e.printStackTrace()
                }
            }
        })
    }
}

MyAdapter.kt:

import android.content.Context
import android.content.Intent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.recyclerview.widget.RecyclerView

class MyAdapter(
    listArray: ArrayList<ListItem>, context: Context
) : RecyclerView.Adapter<MyAdapter.ViewHolder>() {

    var listArrayR = listArray
    var contextR = context

    class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {

        val tvData = view.findViewById<TextView>(R.id.tv_data)
        val tvTitle = view.findViewById<TextView>(R.id.tv_title)
        val tvDescription = view.findViewById<TextView>(R.id.tv_description)
        val tvYoutube = view.findViewById<TextView>(R.id.tv_youtube)

        fun bind(listItem: ListItem, context: Context) {

            tvData.text = listItem.episodeData
            tvTitle.text = listItem.titleText
            tvDescription.text = listItem.contentText
            tvYoutube.text = listItem.youtubeFrame
            itemView.setOnClickListener() {
                val intent = Intent(context, ContentActivity::class.java).apply {
                    putExtra("data", tvData.text.toString())
                    putExtra("title", tvTitle.text.toString())
                    putExtra("description", tvDescription.text.toString())
                    putExtra("youtube", tvYoutube.text.toString())
                }
                context.startActivity(intent)
            }

        }

    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val inflater = LayoutInflater.from(contextR)
        return ViewHolder(inflater.inflate(R.layout.item_layout_main, parent, false))
    }

    override fun getItemCount(): Int {
        return listArrayR.size
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        var listItem = listArrayR[position]
        holder.bind(listItem, contextR)
    }
}

UPD Логи:

2024-06-13 20:24:55.058 15679-15775 AndroidRuntime          ru.aspavlov.theoaesthetics           E  FATAL EXCEPTION: OkHttp Dispatcher
                                                                                                    Process: ru.aspavlov.theoaesthetics, PID: 15679
                                                                                                    android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
                                                                                                        at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:8399)
                                                                                                        at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:1496)
                                                                                                        at android.view.View.requestLayout(View.java:24786)
                                                                                                        at android.view.View.requestLayout(View.java:24786)
                                                                                                        at android.view.View.requestLayout(View.java:24786)
                                                                                                        at android.view.View.requestLayout(View.java:24786)
                                                                                                        at android.view.View.requestLayout(View.java:24786)
                                                                                                        at android.view.View.requestLayout(View.java:24786)
                                                                                                        at androidx.constraintlayout.widget.ConstraintLayout.requestLayout(ConstraintLayout.java:3605)
                                                                                                        at android.view.View.requestLayout(View.java:24786)
                                                                                                        at androidx.recyclerview.widget.RecyclerView.requestLayout(RecyclerView.java:4412)
                                                                                                        at androidx.recyclerview.widget.RecyclerView$RecyclerViewDataObserver.onChanged(RecyclerView.java:5541)
                                                                                                        at androidx.recyclerview.widget.RecyclerView$AdapterDataObservable.notifyChanged(RecyclerView.java:12253)
                                                                                                        at androidx.recyclerview.widget.RecyclerView$Adapter.notifyDataSetChanged(RecyclerView.java:7354)
                                                                                                        at ru.aspavlov.theoaesthetics.MainActivity$onCreate$1.onResponse(MainActivity.kt:53)
                                                                                                        at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:519)
                                                                                                        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
                                                                                                        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
                                                                                                        at java.lang.Thread.run(Thread.java:919)

UPD Проблема: приложение крэшится при запуске.


Ответы (1 шт):

Автор решения: Alexey Pavlov

Всё, разобрался. В последнем случае приложение крэшилось из-за проблем с зависимостями. Сделал даунгрейд, указав в build.gradle.kts (app) более раннюю версию OkHttp:

implementation ("com.squareup.okhttp3:okhttp:4.2.1")

После этого завелось.

Низкий поклон всем, кто принял участие в дискуссии! В особенности благодарю woesss за то, что помог правильно прописать обработку массива JSON.

→ Ссылка