I am working on an android project, in which an ListFragment is being updated from a child activity. However, although the count of elements is correct after the update, the elements themselves are not. Incorrect elements are being put into the list and duplicating each other.
The problem is, after the child activity modifies the file, and calls the populate() function, and then I return to the main activity where the Fragments are, the problem appears.
For example, in the beginning they are in this sequence: [1, 2, 3]
Now the file operation in the child activity gets the item "1" removed (Not directly calling remove, but removing that file, and the populate()
function (listed below) will generate a list without that element), and it should become [2, 3]
. But it becomes [1, 2]
instead.
And after a complete refresh invoked by a button, including clearing and repopulating the MetadataManager.packMap
and PackListManager.onlineList
, PackListManager.localList
, followed by a restart of MainActivity, it returns to normal.
Now we have [2, 3]
. Another file operation in the child activity should get "1" back, and it should become [1, 2, 3]
again. But, it becomes [2, 3, 3]
instead.
The elements are from an ArrayList in a singleton. This is the class of the ListFragment:
class PackListFragment : ListFragment() {
private lateinit var dataList: ArrayList<PackageMetadata>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val index = arguments?.getInt(ARG_SECTION_NUMBER) ?: 1
if (index == 1){
dataList = PackListManager.onlineList
} else {
dataList = PackListManager.localList
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val adapter = PackMetadataAdapter(activity as Context, dataList)
listAdapter = adapter
return inflater.inflate(R.layout.fragment_main, container, false)
}
override fun onResume() {
(listAdapter as ArrayAdapter<PackageMetadata>).notifyDataSetChanged()
super.onResume()
}
My ListView uses a custom adapter. This is the adapter:
class PackMetadataAdapter (context : Context, val values : List<PackageMetadata>)
: ArrayAdapter<PackageMetadata>(context, -1, values) {
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
if (convertView == null) {
val inflater = context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
/*val rowView : View = inflater.inflate(android.R.layout.simple_list_item_1, parent, false)
val text1 = rowView.findViewById(android.R.id.text1) as TextView
text1.text = values[position].Name_LO*/
val metadata = values[position]
val rowView: View = inflater.inflate(R.layout.listitem_route, parent, false)
val textTitle = rowView.findViewById<View>(R.id.textTitle) as TextView
val textAuthor = rowView.findViewById(R.id.textAuthor) as TextView
val textVersion = rowView.findViewById(R.id.textVersion) as TextView
val textTimestamp = rowView.findViewById(R.id.textTimestamp) as TextView
val imageView: ImageView = rowView.findViewById<View>(R.id.imageThumbnail) as ImageView
textTitle.text = metadata.Name_LO
textAuthor.text = metadata.Author.Name_LO
textVersion.text = metadata.Version.get()
textTimestamp.text = SimpleDateFormat("yyyy-MM-dd", Locale.US)
.format(values[position].Timestamp)
DownloadImageTask(imageView).execute(metadata.Thumbnail)
return rowView
}
return convertView
}
}
And that list in the singleton is populated like this:
object PackListManager {
const val LOGCAT_TAG = "BCSPackListMan"
val localList : ArrayList<PackageMetadata> = ArrayList()
var onlineList : ArrayList<PackageMetadata> = ArrayList()
fun populate(){
localList.clear(); onlineList.clear()
val localPacks = HashMap(PackLocalManager.getLocalPacks().map {
val parts = stripExtension(it.nameWithoutExtension).split("_")
if (parts.count() > 1) {
parts[0] to Version(parts[1])
} else {
it.nameWithoutExtension to Version("0.0")
}
}.toMap())
for (pack in MetadataManager.packMap){
if (localPacks.containsKey(pack.key)){
Log.i(LOGCAT_TAG, "Pack "+pack.key+" found on local disk")
if (localPacks[pack.key]!! < pack.value.Version){
Log.i(LOGCAT_TAG, "Pack "+pack.key+" can be updated")
}
localPacks.remove(pack.key)
localList.add(pack.value)
} else {
Log.i(LOGCAT_TAG, "Pack "+pack.key+" not installed")
onlineList.add(pack.value)
}
}
}
By checking the logcat, I can say the list generated by the polulate()
function is correct, while the MetadataManager.packMap shuold remains unchanged if no aforementioned manual refresh is invoked.
I have searched for such problem on google, but I can't seem to find out a nice answer. I am really sorry for posting such long codes, but I really cannot figure it out myself. Any help would be greatly appreciated!
BTW I am not a native speaker so sorry for mistakes in the post.
Do not use ListView
, because it is outdated, instead of this try RecyclerView
.