【问题标题】:Android: cannot refresh Listview using CustomAdapterAndroid:无法使用 CustomAdapter 刷新 Listview
【发布时间】:2017-02-06 10:28:01
【问题描述】:

我需要用新数据刷新列表视图。下面这段代码是用来第一次获取OnCreateView中的数据,即FragmentActivity中的数据。

override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
                          savedInstanceState: Bundle?): View? {
        val url = "something"

        val request_queue = Volley.newRequestQueue(this.context)
        val stringRequest = StringRequest(Request.Method.GET, url,
                Response.Listener<String> { response ->
                    val pending_job = Gson().fromJson<ArrayList<HashMap<String, String>>>(
                            response.toString(),
                            object : TypeToken<ArrayList<HashMap<String, String>>>() {}.type
                    )
                    this@PlaceholderFragment.showList(rootView, R.id.pending_job_list, pending_job)

                    pending_job_list_layout.setOnRefreshListener(this)

                    request_queue.stop()
                }, Response.ErrorListener { error ->
            if (error.networkResponse != null) {
                Toast.makeText(this.context, error.networkResponse.statusCode.toString(), Toast.LENGTH_SHORT).show()
            }
            request_queue.stop()
        })
        request_queue.add(stringRequest)
}

showList是设置CustomAdapter的函数,即

fun showList(rootView: View, tab_id: Int, job_list: ArrayList<HashMap<String, String>>) {

    // custom display ListView
    val adapter: CustomAdapter = CustomAdapter(
            this.context,
            job_list
    )

    this_adapter = adapter

    val listView = rootView.findViewById(tab_id) as ListView
    listView.adapter = adapter
}

,还有这个CustomAdapter 类,

class CustomAdapter(internal var mContext: Context,
                internal var job_list: ArrayList<HashMap<String, String>>
                ) : BaseAdapter() {

override fun getCount(): Int {
    return job_list.size
}

override fun getItem(position: Int): Any? {
    return null
}

override fun getItemId(position: Int): Long {
    return 0
}

override fun getView(position: Int, view: View?, parent: ViewGroup): View {
    val mInflater = mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater

    val item_view = mInflater.inflate(R.layout.activity_job_item, parent, false)

    val job_name: MutableList<String> = arrayListOf()
    job_list.mapTo(job_name) { it["BaseSiteName"] as String }
    val nameView: TextView = item_view.findViewById(R.id.name) as TextView
    nameView.text = job_name[position]

    val job_date: MutableList<String> = arrayListOf()
    job_list.mapTo(job_date) { it["PlanDt"] as String}
    val dateView: TextView = item_view.findViewById(R.id.date) as TextView
    dateView.text = job_date[position]

    item_view.setOnClickListener{
        val intent: Intent = Intent(mContext, JobDetailActivity::class.java)
        intent.putExtra("job", job_list[position])
        mContext.startActivity(intent)
    }

    return item_view
}

}

但是,我想让列表可以刷新。我编写了以下代码来刷新列表。

override fun onRefresh() {
    Toast.makeText(this.context, "Refresh", Toast.LENGTH_SHORT).show()
    val rootView = this_inflater!!.inflate(R.layout.fragment_pending_job, this_container, false)

    val url = "something"

    val request_queue = Volley.newRequestQueue(this.context)
    val stringRequest = StringRequest(Request.Method.GET, url,
            Response.Listener<String> { response ->
                val pending_job = Gson().fromJson<ArrayList<HashMap<String, String>>>(
                        response.toString(),
                        object : TypeToken<ArrayList<HashMap<String, String>>>() {}.type
                )

                val adapter: CustomAdapter = CustomAdapter(
                        this.context,
                        pending_job
                )

                val listView = rootView.findViewById(R.id.pending_job_list) as ListView
                listView.adapter = adapter

                pending_job_list_layout.isRefreshing = false

                pending_job_list_layout.setOnRefreshListener(this)

                request_queue.stop()
            }, Response.ErrorListener { error ->
        if (error.networkResponse != null) {
            Toast.makeText(this.context, error.networkResponse.statusCode.toString(), Toast.LENGTH_SHORT).show()
        }
        request_queue.stop()
    })
    request_queue.add(stringRequest)
}

这只是再次实例化CustomAdapter 并将其再次带到列表视图。

当我刷新时,列表中没有任何变化。

【问题讨论】:

  • 为什么刷新时会放大片段视图?你应该在onCreateView() 部分给它充气。可能您从错误的根(即您新膨胀的根)中获取了 Response.Listener 中的 listView 引用,这就是更新未显示的原因。 (您的屏幕使用旧的 rootView 而您什么也没做)。
  • 这是一个糟糕的实现,为什么你不公开带有数据的 ArrayList 并重新设置它?我的意思是这样的:adapter.job_list = pending_job 然后调用 notifyDataSetChanged() ?
  • 我只需在onRefresh 中添加adapter.job_list,然后调用adapter.notifyDataSetChanged(),就可以了!谢谢大家帮助我。

标签: android android-volley kotlin android-listfragment custom-adapter


【解决方案1】:

在 CustomAdapter 类中定义一个方法UpdateData 将接收新数据并替换旧数据

fun UpdateData(new_job_list: ArrayList<HashMap<String, String>>){
       job_list.clear()
       job_list.addAll(new_job_list)
       notifyDataSetChanged()
   }

现在,当您从 volly 获取新数据时,无需再次为 listview 设置适配器,只需使用

adapter.UpdateData(pending_job)

【讨论】:

    【解决方案2】:

    1.方式: 您可以使用Asynctask 制作后台监听器。您可以在循环中连续监听您的服务器。当数据更改时,您可以刷新listview。这种方式很简单,但不利于性能。

    2.方式: 您可以使用firebase 数据库。因为它是实时工作的。

    3.方式: 如果你不想改变你的数据库。你可以使用Google Cloud Messaging。你必须实现这个,服务器和你的应用程序。当服务器上的数据发生变化时,监听并通过云消息发送消息到android应用程序。并自动刷新list view .

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-10
      相关资源
      最近更新 更多