android - 单击某个对象时重新加载活动?[科特林,安卓]
问题描述
信息
我正在使用 RecyclerView 显示来自 sqlite 数据库的数据。一些对象代表文件夹/层。如果用户单击文件夹/图层,则应显示新数据。需要从数据库中检索新数据。
假设
要显示新数据,需要再次调用 RecyclerViewAdapter(代码片段中的 CustomAdapter)。这导致了我的问题。
问题
如果单击某个对象,我如何设法刷新 Activity?
MainActivity.kt
package com.example.todo
import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.*
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.snackbar.Snackbar
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val spinner: Spinner = findViewById(R.id.create_new)
setAdapter(spinner)
//RecyclerView
createRecyclerView(this)
}
private fun setAdapter(spinner: Spinner) {
ArrayAdapter.createFromResource(
this,
R.array.create_new,
android.R.layout.simple_spinner_item
).also { adapter ->
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
spinner.adapter = adapter
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(
parent: AdapterView<*>?,
view: View,
position: Int,
id: Long
) {
val selected = parent?.getItemAtPosition(position).toString()
if (selected.equals("Ebene")) {
Snackbar.make(view, "spinner: ebene", Snackbar.LENGTH_SHORT).show()
} else if (selected.equals("To-Do-Liste")) {
Snackbar.make(view, "spinner: to-do-liste", Snackbar.LENGTH_SHORT).show()
}
}
override fun onNothingSelected(parent: AdapterView<*>?) {
Log.i("Placeholder", "XXXXXXXXXXX")
}
}
}
}
fun createRecyclerView(context: Context) {
var adapter: RecyclerView.Adapter<CustomAdapter.ViewHolder>? = null
val layoutManager: RecyclerView.LayoutManager = LinearLayoutManager(context)
val recyclerView: RecyclerView = findViewById(R.id.recyclerView)
recyclerView.layoutManager = layoutManager
recyclerView.adapter = CustomAdapter(context)
}
}
CustomAdapter.kt (== RecyclerViewAdapter)
package com.example.todo
import DatabaseHandler
import ParentId
import android.content.Context
import android.database.Cursor
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.cardview.widget.CardView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.recyclerview.widget.RecyclerView
//https://developer.android.com/guide/topics/ui/layout/recyclerview
class CustomAdapter(private val context: Context)
: RecyclerView.Adapter<CustomAdapter.ViewHolder>() {
var data = getDataForRecyclerView()
val entries: Array<String> = data[0] as Array<String>
val types: Array<Int> = data[1] as Array<Int>
class ViewHolder(view: View) : RecyclerView.ViewHolder(view){
val entity: TextView
val entity_container: CardView
val entity_constraint_layout: ConstraintLayout
val entity_icon: ImageView
init {
entity = view.findViewById(R.id.entity)
entity_container = view.findViewById(R.id.entity_container)
entity_constraint_layout = view.findViewById(R.id.entity_constraint_layout)
entity_icon = view.findViewById(R.id.entity_icon)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomAdapter.ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.layout_recycler_layer_tdl,
parent,
false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: CustomAdapter.ViewHolder, position: Int) {
//Der TextView einen String aus dem Datensatz zuweisen.
holder.entity.text = entries[position]
//identifizieren, ob es sich um eine Ebene oder eine TDL handelt
val type = types[position]
if (type==0){
holder.entity_icon.apply {
setImageResource(R.drawable.layer_icon)
contentDescription = "Ebene"
}
} else if (type==1){
holder.entity_icon.apply {
setImageResource(R.drawable.tdl_icon)
contentDescription = "To-Do-Liste"
}
}
//Wenn die jeweilige Cardview gedrückt wird.
holder.entity_container.setOnClickListener{
when {
//geklicktes Objekt ist eine Ebene
types[position] == 0 -> {
val db = DatabaseHandler(context).readableDatabase
val query: String = "Select id from layer where name='${holder.entity.text.toString()}'"
val result = db.rawQuery(query, null)
if (result.count > 0){
result.moveToFirst()
ParentId.parentId = result.getInt(0)
Log.i("oBVH", "Ebene")
//TODO: Refresh MainActivity
}
result.close()
}
//geklicktes Objekt ist eine To-Do-List
types[position] == 1 -> {
Log.i("oBVH", "tdl")
}
else -> {
Log.i("oBVH", "Fehler")
}
}
}
}
override fun getItemCount(): Int = entries.size
fun getDataForRecyclerView(): Array<Any> {
val parentId = ParentId.parentId
val db = DatabaseHandler(context).readableDatabase
val queryLayer = "select name from layer where parent_id=$parentId"
val queryTdl = "select name from tdl where layer_id=$parentId"
val layerResult: Cursor? = db.rawQuery(queryLayer, null)
val tdlResult: Cursor? = db.rawQuery(queryTdl, null)
//Iterator
var i = 0
//Länge des Ziel-Arrays
val length: Int = layerResult?.count!! + tdlResult?.count!!
//String-Array mit Anzahl Elemente == Länge des Cursors, damit mittels set Daten übergeben werden können.
val dataset = Array<String>(length){""}
//Int-Array um später festzustellen, ob ein Entry im CardView eine Ebene oder eine TDL ist
val type = Array<Int>(length){0}
//Betroffene Layer extrahieren und dem dataset String-Array hinzufügen
if (layerResult.count > 0) {
layerResult.moveToFirst()
do {
val data: String = layerResult.getString(layerResult.getColumnIndex("name"))
dataset.set(i, data)
i+=1
} while (layerResult.moveToNext())
}
layerResult.close()
//Betroffene To-Do-Listen extrahieren und dem dataset String-Array hinzufügen
val tdlDataset = Array<String>(tdlResult.count){""}
if (tdlResult.count > 0) {
tdlResult.moveToFirst()
do {
val data: String = tdlResult.getString(tdlResult.getColumnIndex("name"))
dataset.set(i, data)
type.set(i, 1)
i+=1
} while (tdlResult.moveToNext())
}
tdlResult.close()
return arrayOf(dataset, type)
}
}
ParentId.kt(用于更改/检索图层/文件夹)
class ParentId {
companion object {
var parentId: Int = 0
}
}
解决方案
你的问题有一个答案,但如果你做其他事情会更好:
首先:如果只有RecyclerView数据发生变化,可以在更新内部数据后在适配器上调用notifyDataSetChanged。在这样做的同时,您当然还可以更新活动中显示的其他内容,如果这不是唯一的事情。
如果你想要(一个丑陋的)简单的解决方案,也许你可以启动另一个活动并传递一个提示应该在意图中显示哪些数据,例如传递一个文件夹名称,下一个活动知道要显示什么。
编辑:刚刚看到你的 ParentId 类,你通常不会像那样在 Android 中使用静态对象。考虑在将来将其更改为 Intent extras,但您现在可能看不到由于此而导致的错误。
另一种解决方案是使用片段并将当前片段与新片段交换,这与第二种解决方案非常相似,但更好。
最后,第一个选项是最好的。找到一种只更新数据和回收视图的方法,这也允许动画之类的东西,并且可能会导致更少的错误。如果您需要处理后按,您可以使用 onBackPressed()
此外,仅调用 Recyclerview 设置方法(而不是重新启动任何东西)可能已经有所帮助,但我仍然会在之后更改它