Как сделать так, чтобы мой модифицированный вызов отображался в recyclerview?

#android #rest #kotlin #android-recyclerview #retrofit

#Android #отдых #kotlin #android-recyclerview #модернизация

Вопрос:

У меня проблема с отображением моих данных из вызова 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 (адаптер просмотра Recycler):

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

MainActivity:

 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
 

Комментарии:

1. что ж, отладьте его. вы установили точку останова в этой строке : recyclerViewAdapter.setListData(response.body()?.items!!) ? знаете ли вы, возвращаются ли данные из вашего вызова api?

2. @a_local_nobody я понимаю это, но я не знаю, что с этим делать?

3. Ваши объекты json имеют только два свойства, но в классе данных вы пытаетесь получить доступ к еще одному свойству val stock_ID: String . В вашей функции onespose вы можете зарегистрировать response.body() и посмотреть, какой ответ вы получаете?

Ответ №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 в класс object, это поможет вам создать именно то, что необходимо для успешной десериализации. Эта функция Android Studio известна как Kotlin data class file from JSON и может быть найдена в меню File -> New.

Комментарии:

1. OP уже работает recyclerViewAdapter.setListData(response.body()?.items!!) recyclerViewAdapter.notifyDataSetChanged() , поэтому я сомневаюсь, что это что-то изменит

2. Да, это можно добавить в сам адаптер. Я думаю, что ответ от Retrofit неверен, или, может быть, преобразование неверно. Я предлагаю вам использовать StethoInterceptor для перехвата и анализа ваших вызовов API.

3. конечно, но это не заставит код работать по-другому, так что на самом деле это не ответ на вопрос, верно?

4. спасибо, это вроде как работает, потому что, по крайней мере, я получаю обратную связь от этой строки переопределение fun OnFailure(вызов: Вызов<LowStockList>, t: Throwable) { Toast.makeText(это@MainActivity, «Данные Masalah untuk mendapatkan», Toast. LENGTH_LONG).show() } по крайней мере, я знаю проблему из связи с retrofit

5. @PriyanshKedia я попробую посмотреть на stethointercepptor. у меня такое ощущение, что тип передаваемых данных неверен. знаете ли вы, как я могу определить, какая передача данных правильная. tq заранее

Ответ №2:

Проблема может заключаться в назначении нового экземпляра List элементам, когда адаптер содержит другую ссылку, добавьте response в существующий список вместо переназначения экземпляра

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

Комментарии:

1. не могли бы вы немного уточнить? я не совсем понимаю последнюю часть «добавить ответ в существующий список вместо переназначения экземпляра»

2. когда вы создаете экземпляр элементов, он будет передан в качестве источника данных адаптеру, адаптер теперь использует этот экземпляр для проверки изменений в данных, теперь, когда вы это делаете this.items = data , вы указываете элементы на ссылку, поэтому адаптер не будет знать об этом источнике, поэтому вместо этого лучше обновить списоко назначении его data