>

저는 현재 Android 스튜디오를 사용하여 Android 앱을 만들고 있습니다. Kotlin을 사용하여 빌드하고 있으며 앱과 관련된 특정 사항은 다음과 같습니다.

  • BottomNavigationView 를 사용하고 있습니다   NavFragmentView 와 함께   Navigation Graph 를 사용하여 . 그 부분은 잘 작동하고 있습니다.
  • 저는 앱의 주요 섹션 인 기본 조각 5 개를 가지고 있으며 기본적으로 BottonNavigationView 의 항목 중 하나를 탭하면  올바른 조각이 주요 NavFragmentView 로 가져옵니다. .

현재 RecyclerView 를 구현하고 있습니다.   GridLayout 를 사용하여 일종의 달력을 표시합니다. .

사용자 인터페이스를 준비하고 RecyclerView 를 채웠습니다   RecyclerView 에 대한 어댑터 내부 목록의 정적 데이터 .

다음으로 OkHTTP 를 사용하여 API에서 JSON 데이터를 얻는 것이 었습니다  그런 다음 GSON 를 사용하여 형식을 지정하십시오. . 이 시점까지 모든 것이 잘 작동하며 JSON 형식이 올바르게 지정됩니다. 어댑터로 전달하려고 할 때 문제가 시작됩니다.

Kotlin과 Android를 처음 접했을 때 조각에서 직접 항목에 액세스하는 데 문제가 있었기 때문에 조각에 액세스하는 데 문제가 있었지만 조각의 기본보기를 변수에 할당 할 수 있음을 알았습니다. 거기에서 참조하십시오. 그 부분은 내 문제를 부분적으로 수정했습니다. 내 코드는 다음과 같습니다.

MesFragment.kt-메인 뷰를 mesView 에 할당하는 것을 볼 수 있듯이 이것은 조각에 대한 Kotlin 파일입니다.  변수, 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-내 정적 목록에 주석을 달았고 내가하려고하는 유일한 UI 변경은 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

    OkHttpClient는 백그라운드 스레드에서 콜백을 호출합니다.

    따라서 :

    1.) 대신 Retrofit을 사용하면 UI 스레드에서 콜백을 호출합니다.

    2.) 핸들러를 사용하여 백그라운드 스레드에서 UI 스레드로 돌아갑니다.

    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")
            }
    })
    
    

  • 이전 javascript - 반응 네이티브에서 기본 탐색 애니메이션을 변경하는 방법
  • 다음 c# - 엔티티 프레임 워크를 사용하여 저장 프로 시저를 호출 할 때 결과로 JSON을 가져올 때 반환 유형 오류