GridView 和动态数据

GridView and dynamic data

我从服务器下载了数据,但没有显示出来。如果从顶部放下快门,数据将加载到 GridView

已尝试所有选项,从服务器读取数据正常,但未加载到GridView。请告诉我,问题是什么?

适配器:

private val list = list
override fun getView(position:Int, convertView: View?, parent: ViewGroup?):View{
    // Inflate the custom view
    val inflater = parent?.context?.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
    val view = inflater.inflate(R.layout.shop_item,null)

    // Get the custom view widgets reference
    val tv = view.findViewById<TextView>(R.id.tv_name)
    val card = view.findViewById<CardView>(R.id.card_view)

    // Display color name on text view
    tv.text = list[position].name

    Picasso.get().load("http://first-gadget.ru/" + list[position].img).into(view.image)

    // Set a click listener for card view
    card.setOnClickListener{
        // Show selected color in a toast message
        Toast.makeText(parent.context,
                "Clicked : ${list[position].name}",Toast.LENGTH_SHORT).show()
    }

    // Finally, return the view
    return view
}

Activity:

private lateinit var title: String
private var adapter: CategoryBaseAdapter? = null

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_category)

    adapter = CategoryBaseAdapter(getCategoryItemsFromServer())
    grid_view.adapter = adapter

    // Configure the grid view
    grid_view.numColumns = 2
    grid_view.horizontalSpacing = 30
    grid_view.verticalSpacing = 30
    grid_view.stretchMode = GridView.STRETCH_COLUMN_WIDTH

}

private fun getCategoryItemsFromServer(): ArrayList<Items> {
    val list = ArrayList<Items>()
    val url = "http://first-gadget.ru/api/shop.php"

    val requestBody = MultipartBody.Builder()
        .setType(MultipartBody.FORM)
        .addFormDataPart("category", "cars")
        .build()

    val request = Request.Builder().url(url).post(requestBody).build()
    var client = OkHttpClient()

    client.newCall(request).enqueue(object: Callback {
        override fun onResponse(call: Call, response: Response) {
            val body = response.body()?.string()
            val obj = JSONObject(body)
            val array = obj.getJSONArray("array")
            for (i in 0 until array.length()) {
                var detail: JSONObject =array.getJSONObject(i)
                list.add(Items(detail.getInt("id"), detail.getString("name"), detail.getString("img")))
            }
        }
        override fun onFailure(call: Call, e: IOException) {
            Toast.makeText(this@CategoriesActivity, "Sasat", Toast.LENGTH_SHORT).show()
        }
    })
    return list
}

private fun getCategoryItemsFromServer() 返回空列表。 您可以在 enqueue

中设置适配器
 for (i in 0 until array.length()) {
            var detail: JSONObject =array.getJSONObject(i)
            list.add(Items(detail.getInt("id"), detail.getString("name"), detail.getString("img")))
        }
adapter = CategoryBaseAdapter(list)

或修改CategoryBaseAdapter添加方法fun addItems(list:ArrayList<Items>)notifyDataSetChanged()

由于 getCategoryItemsFromServer 是异步的,我不确定启动适配器时是否检索了项目。 在 getCategoryItemsFromServer 的 onResponse 中启动您的适配器。并且可以在线程中使用 join 方法调用此方法,以确保线程在继续之前已经结束。

编辑:不要更改任何内容,只需在 onResponse 结束时调用 adapter.notifyDataSetChanged() 即可。当项目存在时刷新适配器

我查看了您的代码,发现问题是由于调用 -

adapter = CategoryBaseAdapter(getCategoryItemsFromServer())
grid_view.adapter = adapter

当为 CategoryBaseAdapter 创建构造函数并将 getCategoryItemsFromServer() 作为参数传递但在从服务器(通过另一个线程)获得响应之前,主线程将使用空列表完成流程。因此,那里不会显示任何数据。现在,当接收到服务器数据时,适配器将无事可做。

现在的解决方案是,一旦从服务器收到数据就调用您的适配器,或者在填充数据后调用 notifyDataSetChanged()。所以最终代码将是

    private lateinit var title: String
private var adapter: CategoryBaseAdapter? = null
val list = ArrayList<Items>()

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_category)

    //Creating adapter with empty list
    adapter = CategoryBaseAdapter(list)
    grid_view.adapter = adapter

    // Configure the grid view
    grid_view.numColumns = 2
    grid_view.horizontalSpacing = 30
    grid_view.verticalSpacing = 30
    grid_view.stretchMode = GridView.STRETCH_COLUMN_WIDTH

    //Calling server to populate list
    getCategoryItemsFromServer()
}

private fun getCategoryItemsFromServer() {

    val url = "http://first-gadget.ru/api/shop.php"

    val requestBody = MultipartBody.Builder()
        .setType(MultipartBody.FORM)
        .addFormDataPart("category", "cars")
        .build()

    val request = Request.Builder().url(url).post(requestBody).build()
    var client = OkHttpClient()

    client.newCall(request).enqueue(object: Callback {
        override fun onResponse(call: Call, response: Response) {
            val body = response.body()?.string()
            val obj = JSONObject(body)
            val array = obj.getJSONArray("array")
            for (i in 0 until array.length()) {
                var detail: JSONObject =array.getJSONObject(i)
                list.add(Items(detail.getInt("id"), detail.getString("name"), detail.getString("img")))
            }

            //List populated from server data, now refreshing to populated updated one.
            adapter.notifyDataSetChanged();
        }
        override fun onFailure(call: Call, e: IOException) {
            Toast.makeText(this@CategoriesActivity, "Sasat", Toast.LENGTH_SHORT).show()
        }
    })
}

现在在适配器内部,不要创建列表对象,而是创建一个列表引用变量并评估从适配器构造函数调用(即来自 activity onCreate())收到的列表值。