Android:如何从外部Activity更新ListView内容?
Hey there! Let's tackle how to update your MainActivity's SimpleListView from AddingItemsActivity — I've got two solid approaches that fit right into your project setup.
Approach 1: Use Activity Result Callbacks (Recommended for Basic Scenarios)
This is Android's modern, recommended way to pass data back from one Activity to another, replacing the old startActivityForResult API.
Step 1: Register a Result Launcher in MainActivity
First, set up a launcher to listen for results from AddingItemsActivity:
// MainActivity.kt private val addItemLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> if (result.resultCode == RESULT_OK) { // Retrieve the new/updated SimpleItem from the result intent val modifiedItem = result.data?.getParcelableExtra<SimpleItem>("MODIFIED_ITEM") modifiedItem?.let { item -> // Assume you have a mutable list holding your data (e.g., private val items = mutableListOf<SimpleItem>()) val existingIndex = items.indexOfFirst { it.id == item.id } if (existingIndex != -1) { // Update existing item items[existingIndex] = item itemAdapter.notifyItemChanged(existingIndex) } else { // Add new item items.add(item) itemAdapter.notifyItemInserted(items.size - 1) } } } }
Step 2: Launch AddingItemsActivity
Trigger the Activity from your add/update button in MainActivity:
btnAddOrUpdate.setOnClickListener { val intent = Intent(this, AddingItemsActivity::class.java) // If you're updating an existing item, pass it to the Activity here: // intent.putExtra("EDIT_ITEM", itemToEdit) addItemLauncher.launch(intent) }
Step 3: Return Data from AddingItemsActivity
Once the user finishes adding/updating an item, send the data back to MainActivity:
// AddingItemsActivity.kt btnSave.setOnClickListener { val itemName = etItemName.text.toString().trim() if (itemName.isNotEmpty()) { // Create or update the SimpleItem val modifiedItem = intent.getParcelableExtra<SimpleItem>("EDIT_ITEM")?.copy(name = itemName) ?: SimpleItem(id = System.currentTimeMillis(), name = itemName) // Package the item and send it back val resultIntent = Intent().apply { putExtra("MODIFIED_ITEM", modifiedItem) } setResult(RESULT_OK, resultIntent) finish() } }
Important: Make SimpleItem Parcelable
To pass SimpleItem via Intent, it needs to implement the Parcelable interface:
// SimpleItem.kt data class SimpleItem(val id: Long, val name: String) : Parcelable { constructor(parcel: Parcel) : this( parcel.readLong(), parcel.readString() ?: "" ) override fun writeToParcel(parcel: Parcel, flags: Int) { parcel.writeLong(id) parcel.writeString(name) } override fun describeContents(): Int = 0 companion object CREATOR : Parcelable.Creator<SimpleItem> { override fun createFromParcel(parcel: Parcel): SimpleItem = SimpleItem(parcel) override fun newArray(size: Int): Array<SimpleItem?> = arrayOfNulls(size) } }
Approach 2: Use ViewModel + LiveData (Best for Complex/Shared Data)
If you want a more robust solution that handles configuration changes (like screen rotation) and keeps data decoupled from Activities, use Android Architecture Components.
Step 1: Create a Shared ViewModel
This ViewModel will hold your item data and handle updates:
// ItemViewModel.kt class ItemViewModel : ViewModel() { private val _items = MutableLiveData<MutableList<SimpleItem>>(mutableListOf()) val items: LiveData<MutableList<SimpleItem>> = _items fun addItem(item: SimpleItem) { val currentItems = _items.value ?: mutableListOf() currentItems.add(item) _items.postValue(currentItems) } fun updateItem(updatedItem: SimpleItem) { val currentItems = _items.value ?: mutableListOf() val index = currentItems.indexOfFirst { it.id == updatedItem.id } if (index != -1) { currentItems[index] = updatedItem _items.postValue(currentItems) } } }
Step 2: Connect MainActivity to the ViewModel
Observe the LiveData to automatically refresh the ListView when data changes:
// MainActivity.kt private lateinit var viewModel: ItemViewModel private lateinit var itemAdapter: ItemAdapter override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) viewModel = ViewModelProvider(this)[ItemViewModel::class.java] itemAdapter = ItemAdapter(viewModel.items.value ?: mutableListOf()) SimpleListView.adapter = itemAdapter // Refresh adapter whenever the item list updates viewModel.items.observe(this) { newItems -> itemAdapter.updateData(newItems) } btnAddItem.setOnClickListener { startActivity(Intent(this, AddingItemsActivity::class.java)) } }
Step 3: Update Adapter to Support Data Changes
Add a method to your ItemAdapter to update the dataset efficiently:
// ItemAdapter.kt class ItemAdapter(private var items: MutableList<SimpleItem>) : BaseAdapter() { override fun getCount(): Int = items.size override fun getItem(position: Int): SimpleItem = items[position] override fun getItemId(position: Int): Long = items[position].id override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View { // Implement your view inflation and binding here as usual } fun updateData(newItems: MutableList<SimpleItem>) { this.items = newItems // For better performance, use DiffUtil instead of notifyDataSetChanged notifyDataSetChanged() } }
Step 4: Modify Data from AddingItemsActivity
Directly update the ViewModel from AddingItemsActivity — no need to pass data via Intent:
// AddingItemsActivity.kt private lateinit var viewModel: ItemViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_adding_items) viewModel = ViewModelProvider(this)[ItemViewModel::class.java] val editItem = intent.getParcelableExtra<SimpleItem>("EDIT_ITEM") // Pre-fill the input if editing an existing item editItem?.let { etItemName.setText(it.name) } btnSave.setOnClickListener { val itemName = etItemName.text.toString().trim() if (itemName.isNotEmpty()) { val modifiedItem = editItem?.copy(name = itemName) ?: SimpleItem(id = System.currentTimeMillis(), name = itemName) if (editItem != null) viewModel.updateItem(modifiedItem) else viewModel.addItem(modifiedItem) finish() } } }
Quick Tips
- For better adapter performance, replace
notifyDataSetChanged()with DiffUtil to only update changed items. - The ViewModel approach is ideal if you plan to expand your app (e.g., add Fragments that share the same item data).
内容的提问来源于stack exchange,提问作者Czarek

