【问题标题】:How to make my retrofit call appear in recyclerview?如何让我的改造电话出现在 recyclerview 中?
【发布时间】:2021-05-26 11:28:54
【问题描述】:

我在将来自 rest api 调用的数据显示在我的 recyclerview 上时遇到问题。 build 和 logcat 没有错误,可以在模拟器中正常打开而不会崩溃,并且可以显示其他功能。只是这部分 recyclerview 没有显示来自改造调用的任何数据。我正在尝试许多教程/解决方案,但没有一个有效。

这是我的 JSON 数据,我想获取库存的名称和数量:

13{
"body": [
    {
        "stock_ID": "1004",
        "stock_name": "kobis",
        "stock_quantity": "2"
    },
    {
        "stock_ID": "1005",
        "stock_name": "bawang",
        "stock_quantity": "2"
    },
    {
        "stock_ID": "2001",
        "stock_name": "ayam",
        "stock_quantity": "4"
    },
    {
        "stock_ID": "2003",
        "stock_name": "kambing",
        "stock_quantity": "1"
    },
    {
        "stock_ID": "3001",
        "stock_name": "kayu manis",
        "stock_quantity": "2"
    },
    {
        "stock_ID": "3002",
        "stock_name": "lada hitam",
        "stock_quantity": "3"
    },
    {
        "stock_ID": "4001",
        "stock_name": "minyak",
        "stock_quantity": "1"
    },
    {
        "stock_ID": "4002",
        "stock_name": "gula",
        "stock_quantity": "5"
    },
    {
        "stock_ID": "4003",
        "stock_name": "garam",
        "stock_quantity": "5"
    },
    {
        "stock_ID": "4004",
        "stock_name": "kicap",
        "stock_quantity": "4"
    },
    {
        "stock_ID": "4005",
        "stock_name": "beras",
        "stock_quantity": "3"
    },
    {
        "stock_ID": "5001",
        "stock_name": "cawan",
        "stock_quantity": "5"
    }
],
"inventoryCount": 13

}

我的数据类(LowStockItem.kt):

data class LowStockList(val items: ArrayList<LowStockItem>)
data class LowStockItem(
val stock_ID: String,
val stock_name: String,
val stock_quantity: String,)

RestApiService.kt:

@GET ("/inventory/read_lowstock.php")
fun getsLowStock(): Call<LowStockList>

RestApiInstance.kt

    companion object {

    var BASE_URL = "http://roslibiz.com/api/"

    fun getRestApiInstance() : Retrofit {

        return Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .build()

    }
}

LowStockAdapter(回收者视图适配器):

class LowStockAdapter: RecyclerView.Adapter<LowStockAdapter.MyViewHolder>() {

var items = ArrayList<LowStockItem>()

fun setListData(data: ArrayList<LowStockItem>) {
    this.items = data
notifyDataSetChanged()
}

override fun onCreateViewHolder(
    parent: ViewGroup,
    viewType: Int
): MyViewHolder {
    val inflater = LayoutInflater.from(parent.context).inflate(R.layout.low_stock_card, parent, false)

    return MyViewHolder(inflater)
}

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

override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
    holder.bind(items[position])
}



class MyViewHolder(view: View): RecyclerView.ViewHolder(view) {
    val nama = view.namaLSrv
    val id = view.idLSrv
    val kuantiti = view.kuantitiLSrv

    fun bind(data: LowStockItem){
        id.text = data.stock_ID
        if(!TextUtils.isEmpty(data.stock_name)){
            nama.text = data.stock_name
            kuantiti.text = data.stock_quantity
        }else{
            nama.text = "Nama tiada dalam rekod"
            kuantiti.text = "0"
        }
    }
}
}

主活动:

lateinit var recyclerViewAdapter: LowStockAdapter
private fun setupRV(){
    lowStockRV.apply {
        layoutManager = LinearLayoutManager(this@MainActivity)
        recyclerViewAdapter = LowStockAdapter()
        adapter = recyclerViewAdapter

        val decoration = DividerItemDecoration(applicationContext, VERTICAL)
        addItemDecoration(decoration)
}
    private fun getLowStock(){

    val retroInstance = RestApiInstance.getRestApiInstance().create(RestApiService::class.java)
    val call = retroInstance.getsLowStock()

    call.enqueue(object: retrofit2.Callback<LowStockList>{
        override fun onResponse(call: Call<LowStockList>, response: Response<LowStockList>) {
            if (response.isSuccessful){
                recyclerViewAdapter.setListData(response.body()?.items!!)
            }
        }

        override fun onFailure(call: Call<LowStockList>, t: Throwable) {
            Toast.makeText(this@MainActivity, "Masalah untuk mendapatkan data", Toast.LENGTH_LONG).show()
        }
    })
}

我不知所措,需要其他方面的帮助。提前谢谢你。

编辑。 这是我从调试中得到的,老实说我不知道​​该怎么做。

02/24 15:04:25: Launching 'app' on Pixel 2 XL API 30.
Install successfully finished in 688 ms.
$ adb shell am start -n "com.example.roslibusiness/com.example.roslibusiness.ui.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER -D
Waiting for application to come online: com.example.roslibusiness.test | com.example.roslibusiness
Waiting for application to come online: com.example.roslibusiness.test | com.example.roslibusiness
Waiting for application to come online: com.example.roslibusiness.test | com.example.roslibusiness
Connecting to com.example.roslibusiness
Connected to the target VM, address: 'localhost:63581', transport: 'socket'
Capturing and displaying logcat messages from application. This behavior can be disabled in the "Logcat output" section of the "Debugger" settings page.
I/e.roslibusines: Not late-enabling -Xcheck:jni (already on)
I/e.roslibusines: Unquickening 12 vdex files!
W/e.roslibusines: Unexpected CPU variant for X86 using defaults: x86
W/ActivityThread: Application com.example.roslibusiness is waiting for the debugger on port 8100...
I/System.out: Sending WAIT chunk
I/System.out: Debugger has connected
    waiting for debugger to settle...
I/System.out: waiting for debugger to settle...
I/chatty: uid=10153(com.example.roslibusiness) identical 5 lines
I/System.out: waiting for debugger to settle...
I/System.out: debugger has settled (1362)
D/NetworkSecurityConfig: No Network Security Config specified, using platform default
D/NetworkSecurityConfig: No Network Security Config specified, using platform default
I/MultiDex: VM with version 2.1.0 has multidex support
    Installing application
    VM has multidex support, MultiDex support library is disabled.
D/libEGL: loaded /vendor/lib/egl/libEGL_emulation.so
D/libEGL: loaded /vendor/lib/egl/libGLESv1_CM_emulation.so
D/libEGL: loaded /vendor/lib/egl/libGLESv2_emulation.so
W/e.roslibusines: Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (greylist, reflection, allowed)
    Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (greylist, reflection, allowed)
W/e.roslibusines: Accessing hidden method Ljava/lang/invoke/MethodHandles$Lookup;-><init>(Ljava/lang/Class;I)V (greylist, reflection, allowed)
W/e.roslibusines: Accessing hidden method Ldalvik/system/CloseGuard;->get()Ldalvik/system/CloseGuard; (greylist,core-platform-api, reflection, allowed)
    Accessing hidden method Ldalvik/system/CloseGuard;->open(Ljava/lang/String;)V (greylist,core-platform-api, reflection, allowed)
    Accessing hidden method Ldalvik/system/CloseGuard;->warnIfOpen()V (greylist,core-platform-api, reflection, allowed)
D/CompatibilityChangeReporter: Compat change id reported: 147798919; UID 10153; state: ENABLED
D/HostConnection: HostConnection::get() New Host Connection established 0xea4a3c50, tid 7992
D/HostConnection: HostComposition ext ANDROID_EMU_CHECKSUM_HELPER_v1 ANDROID_EMU_native_sync_v2 ANDROID_EMU_native_sync_v3 ANDROID_EMU_native_sync_v4 ANDROID_EMU_dma_v1 ANDROID_EMU_direct_mem ANDROID_EMU_host_composition_v1 ANDROID_EMU_host_composition_v2 ANDROID_EMU_vulkan ANDROID_EMU_deferred_vulkan_commands ANDROID_EMU_vulkan_null_optional_strings ANDROID_EMU_vulkan_create_resources_with_requirements ANDROID_EMU_YUV_Cache ANDROID_EMU_async_unmap_buffer ANDROID_EMU_vulkan_ignored_handles ANDROID_EMU_vulkan_free_memory_sync ANDROID_EMU_vulkan_shader_float16_int8 ANDROID_EMU_vulkan_async_queue_submit GL_OES_EGL_image_external_essl3 GL_OES_vertex_array_object GL_KHR_texture_compression_astc_ldr ANDROID_EMU_host_side_tracing ANDROID_EMU_gles_max_version_3_0 
W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
D/EGL_emulation: eglCreateContext: 0xea483f10: maj 3 min 0 rcv 3
D/EGL_emulation: eglMakeCurrent: 0xea483f10: ver 3 0 (tinfo 0xbbc39170) (first time)
I/Gralloc4: mapper 4.x is not supported
D/HostConnection: createUnique: call
    HostConnection::get() New Host Connection established 0xea483d50, tid 7992
D/goldfish-address-space: allocate: Ask for block of size 0x100
    allocate: ioctl allocate returned offset 0x3fbc17000 size 0x2000
D/HostConnection: HostComposition ext ANDROID_EMU_CHECKSUM_HELPER_v1 ANDROID_EMU_native_sync_v2 ANDROID_EMU_native_sync_v3 ANDROID_EMU_native_sync_v4 ANDROID_EMU_dma_v1 ANDROID_EMU_direct_mem ANDROID_EMU_host_composition_v1 ANDROID_EMU_host_composition_v2 ANDROID_EMU_vulkan ANDROID_EMU_deferred_vulkan_commands ANDROID_EMU_vulkan_null_optional_strings ANDROID_EMU_vulkan_create_resources_with_requirements ANDROID_EMU_YUV_Cache ANDROID_EMU_async_unmap_buffer ANDROID_EMU_vulkan_ignored_handles ANDROID_EMU_vulkan_free_memory_sync ANDROID_EMU_vulkan_shader_float16_int8 ANDROID_EMU_vulkan_async_queue_submit GL_OES_EGL_image_external_essl3 GL_OES_vertex_array_object GL_KHR_texture_compression_astc_ldr ANDROID_EMU_host_side_tracing ANDROID_EMU_gles_max_version_3_0 
I/OpenGLRenderer: Davey! duration=1136ms; Flags=1, IntendedVsync=9582448914498, Vsync=9582548914494, OldestInputEvent=9223372036854775807, NewestInputEvent=0, HandleInputStart=9582554363800, AnimationStart=9582555337800, PerformTraversalsStart=9582555413300, DrawStart=9583238424100, SyncQueued=9583494447900, SyncStart=9583496712300, IssueDrawCommandsStart=9583496796500, SwapBuffers=9583584814100, FrameCompleted=9583588012900, DequeueBufferDuration=571700, QueueBufferDuration=1002300, GpuCompleted=8029250115450508212, 
I/Choreographer: Skipped 56 frames!  The application may be doing too much work on its main thread.

编辑:我应该如何处理这个错误?

E/Retrofit Error: retrofit2.DefaultCallAdapterFactory$ExecutorCallbackCall@ccab847

【问题讨论】:

  • 好吧,调试它。你有没有在这一行设置断点:recyclerViewAdapter.setListData(response.body()?.items!!)?你知道你的 api 调用是否返回了数据吗?
  • @a_local_nobody 我明白了,但我不知道该怎么办?
  • 您的 json 对象只有两个属性,但在数据类中,您正尝试访问另一个属性 val stock_ID: String。在您的 onRespose 函数中,您可以记录 response.body() 并查看您收到的响应是什么?

标签: android rest kotlin android-recyclerview retrofit


【解决方案1】:

你应该改变你的函数setListData的定义

目前是这个

fun setListData(data: ArrayList<LowStockItem>) {
    this.items = data
}

应该改成

fun setListData(data: ArrayList<LowStockItem>) {
    this.items = data
    notifyDataSetChanged()
}

这是从类中通知适配器的更好方法。

notifyDataSetChanged() 通知您的适配器数据已更改以供 RecyclerView 使用,因此适配器会查看新数据并相应地对其进行扩充。

还要确保您在适配器中传递正确的数据。

您在上面发布的改造数据不包含您在课堂上声明的 ID 字段。在这种情况下,它可能会引发一些错误。正如您在 Kotlin 中一样,您可以使用 Android Studio 功能将您的 json 数据直接转换为对象类,这将帮助您准确创建成功反序列化所需的内容。此 Android Studio 功能称为 Kotlin data class file from JSON,可在文件 -> 新建下找到。

【讨论】:

  • OP 已经在做 recyclerViewAdapter.setListData(response.body()?.items!!) recyclerViewAdapter.notifyDataSetChanged() 所以我怀疑这会有所作为
  • 是的,它可以添加到适配器本身。我认为 Retrofit 的反应是不对的,或者转换是不对的。我建议你使用 StethoInterceptor 来拦截和分析你的 API 调用。
  • 当然,但它不会使代码的工作方式有任何不同,所以它并不能真正回答问题,对吧?
  • 谢谢,这有点用,因为至少我从这条线上得到反馈,覆盖乐趣 onFailure(call: Call, t: Throwable) { Toast.makeText(this@MainActivity, "Masalah untuk mendapatkan data", Toast.LENGTH_LONG).show() } 至少我知道与改造连接的问题
  • @PriyanshKedia 我会尝试查看听诊器。我感觉我传递的数据类型不正确。你知道我怎样才能确定哪些数据传递是正确的。 tq提前
【解决方案2】:

问题是将List 的新实例分配给项目,当适配器持有不同的引用时,将response 添加到现有列表而不是重新分配实例

fun setListData(data: ArrayList<LowStockItem>) {
    this.items.clear()
    this.items.addAll(data) 
}

【讨论】:

  • 你能澄清一下吗?我不太明白最后一部分“添加对现有列表的响应而不是重新分配实例”
  • 当您创建项目实例时,它将作为数据源传递给适配器,适配器现在使用该实例来检查数据的变化,现在当您执行this.items = data 时,您将项目指向参考,因此适配器不会知道该来源,因此最好更新列表而不是将其分配给data
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-15
  • 2020-02-26
  • 2023-03-17
相关资源
最近更新 更多