Проблема, пытающаяся повлиять на представления внутри фрагмента - PullRequest
0 голосов
/ 04 мая 2019

Итак, я сейчас создаю приложение для Android, используя Android studio.Я создаю его, используя Kotlin, и конкретные пункты, касающиеся приложения:

  • Я использую BottomNavigationView с NavFragmentView, используя Navigation Graph.Эта часть работает нормально.
  • У меня есть 5 основных фрагментов, которые являются основными разделами приложения, и в основном, когда вы нажимаете на один из элементов BottonNavigationView, правильный фрагмент переносится на основной NavFragmentView.

В настоящее время я застрял в реализации RecyclerView, который отображает вид календаря с использованием GridLayout.

. Я подготовил пользовательский интерфейс и заполнил * 1018.* со статическими данными из списка внутри моего адаптера для RecyclerView.

Следующее, что я сделал, было получение моих данных JSON из моего API с использованием OkHTTP, а затем присвоение им формата с использованием GSON.Все до этого момента работает нормально, JSON корректно форматируется и получается.Проблема начинается, когда я хочу передать ее адаптеру.

У меня были некоторые проблемы с доступом к чему-либо до этого, потому что, поскольку я новичок в Kotlin и Android, у меня были проблемы с доступом к материалам непосредственно из фрагмента, но потомЯ обнаружил, что могу назначить основной вид фрагмента переменной и обратиться к нему оттуда.Эта часть частично исправила мои проблемы.Итак, мой код выглядит примерно так:

MesFragment.kt - это файл Kotlin для моего фрагмента, как вы можете видеть, я назначаю свой основной вид переменной mesView, мне пришлосьсоздайте его вне основной функции, потому что при попытке назначить адаптер в функции fetchMes() у него не было доступа к представлению

class MesFragment : Fragment() {

    var mesView : View? = null

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

        mesView = inflater.inflate(R.layout.fragment_mes, container, false)
        //mesView.calendario_mes.adapter = MesAdapter()

        fetchInfoMes("201905")

        return mesView

    }


    fun fetchInfoMes(mes: String) {
        val url = "https://www.myoriginalsite.com/api/mes/"+ mes +"/-0500/norte"

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

        val client = OkHttpClient()
        client.newCall(request).enqueue(object: Callback {

            override fun onResponse(call: Call, response: Response) {
                var body = response.body()?.string()

                val gson = GsonBuilder().create()

                val mesFeed : List<FechaCompleta> = gson.fromJson(body, object: TypeToken<List<FechaCompleta>>() {}.type)

                mesView?.calendario_mes?.adapter = MesAdapter(mesFeed)
            }

            override fun onFailure(call: Call, e: IOException) {
                println("Error")
            }

        })
    }

}

class FechaCompleta(val vacia: Boolean, val imagen_signo: String, val imagen_luna: String, val fecha: String, val dia: String, val id_entrada: Int)

MesAdapter.kt - это мойАдаптер, как вы можете видеть, я прокомментировал мой статический список, и единственное изменение пользовательского интерфейса, которое я пытаюсь сделать, это mes_fecha.text

class MesAdapter(val mesFeed: List<FechaCompleta>): RecyclerView.Adapter<MesViewHolder>() {

    //val list = listOf<String>("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31")

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MesViewHolder {
        val layoutInflater = LayoutInflater.from(parent?.context)
        val cell = layoutInflater.inflate(R.layout.celda_mes_layout, parent, false)

        return MesViewHolder(cell)
    }

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

    override fun onBindViewHolder(holder: MesViewHolder, position: Int) {
        holder?.view?.mes_fecha.text = mesFeed[position].dia
    }

}

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

}

После открытия фрагмента приложение закрывается, и я получаюэта ошибка:

E/AndroidRuntime: FATAL EXCEPTION: OkHttp Dispatcher
    Process: com.testing.fragmentapp, PID: 8148
    android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

1 Ответ

0 голосов
/ 08 мая 2019

OkHttpClient вызывает обратный вызов в фоновом потоке.

Так что вы должны либо:

1.) Вместо этого используйте Retrofit, который вызывает ваш обратный вызов в потоке пользовательского интерфейса

2.) Вернитесь к потоку пользовательского интерфейса из фонового потока, используя обработчик

private val handler = Handler(Looper.getMainLooper())

call.enqueue(object: Callback {
        override fun onResponse(call: Call, response: Response) {
            var body = response.body()?.string()

            val gson = GsonBuilder().create()

            val mesFeed : List<FechaCompleta> = gson.fromJson(body, object: TypeToken<List<FechaCompleta>>() {}.type)

            handler.post {
                mesView?.calendario_mes?.adapter = MesAdapter(mesFeed)
            }
        }

        override fun onFailure(call: Call, e: IOException) {
            println("Error")
        }
})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...