#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