GridView и динамические данные - PullRequest
0 голосов
/ 21 июня 2019

Я загружаю данные с сервера, и они не отображаются. Если вы опустите затвор сверху, данные будут загружены в GridView.

Уже опробованы все опции, данные с сервера читаются нормально, но не загружаются в GridView. Подскажите, пожалуйста, в чем проблема?

Adapter:

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
}

Активность:

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
}

Ответы [ 3 ]

0 голосов
/ 21 июня 2019

Поскольку getCategoryItemsFromServer является асинхронным, я не уверен, что элементы извлекаются при запуске адаптера.Инициируйте свой адаптер в ответном ответе getCategoryItemsFromServer.И, возможно, вызовите этот метод в потоке с помощью метода соединения, чтобы убедиться, что поток закончен, прежде чем продолжать.

Редактирование: ничего не меняйте, просто вызовите adapter.notifyDataSetChanged () в конце onResponse.Работа.Которые обновляют адаптер при наличии предметов

0 голосов
/ 21 июня 2019

Я изучил ваш код и понял, что проблема возникает из-за вызова of-

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

Теперь внутри адаптера не создавайте объект списка, а создайте переменную ссылки на список и задавайте значение списка, полученное из вызова конструктора адаптера (т. Е. Из действия onCreate).()).

0 голосов
/ 21 июня 2019

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()

...