无需刷新Activity,将ActivityC更新数据同步至ActivityA的实现方案
Hey there! Let's break down two solid solutions for your needs—both let you update ActivityA without refreshing any screens, which is exactly what you're asking for.
For your basic three-Activity setup, Jetpack LiveData + Shared ViewModel is the cleanest, most maintainable approach. It lets you share data across components without relying on static variables or messy intent extras, and updates happen automatically.
Step-by-Step Implementation:
Create a Shared ViewModel
This will hold the mutable user name data and act as the single source of truth for all Activities.import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel class SharedUserViewModel : ViewModel() { // LiveData to hold the user name—MutableLiveData lets us update its value val userName = MutableLiveData<String>() }Observe Data in ActivityA
ActivityA will watch the LiveData and update its TextView as soon as the data changes.import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import androidx.lifecycle.ViewModelProvider import kotlinx.android.synthetic.main.activity_a.* class ActivityA : AppCompatActivity() { private lateinit var viewModel: SharedUserViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_a) // Get the same ViewModel instance across all Activities (using Application as the owner) viewModel = ViewModelProvider( this.application, ViewModelProvider.AndroidViewModelFactory(this.application) )[SharedUserViewModel::class.java] // Observe the LiveData—this block runs every time the userName value changes viewModel.userName.observe(this) { updatedName -> tv_user_name.text = updatedName } } }Update Data in ActivityC
When the save button is clicked, update the LiveData value. ActivityA's observer will trigger instantly, no refresh needed.import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import androidx.lifecycle.ViewModelProvider import kotlinx.android.synthetic.main.activity_c.* class ActivityC : AppCompatActivity() { private lateinit var viewModel: SharedUserViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_c) // Get the same shared ViewModel viewModel = ViewModelProvider( this.application, ViewModelProvider.AndroidViewModelFactory(this.application) )[SharedUserViewModel::class.java] btn_save.setOnClickListener { val newName = et_user_name.text.toString().trim() if (newName.isNotEmpty()) { // Update the LiveData—this triggers ActivityA's observer viewModel.userName.value = newName finish() // Optional: Close ActivityC after saving } } } }ActivityB Just Handles Navigation
No data logic here—just a button that starts ActivityC.btn_go_to_c.setOnClickListener { startActivity(Intent(this, ActivityC::class.java)) }
For your production project where you need to save user location to a server and update ActivityA, we'll extend the above pattern with a Repository to handle network calls (using Retrofit + Coroutines for async work).
Step-by-Step Implementation:
Add Repository for Network Logic
Separate API calls from the ViewModel to keep code clean and testable.import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import retrofit2.Response // Repository class to handle network operations class LocationRepository(private val apiService: LocationApiService) { suspend fun saveLocationToServer(location: String): Result<String> { return withContext(Dispatchers.IO) { try { val response = apiService.saveUserLocation(LocationRequest(location)) if (response.isSuccessful) { // Return the updated location from the server Result.success(response.body()?.updatedLocation ?: location) } else { Result.failure(Throwable("Failed to save location")) } } catch (e: Exception) { Result.failure(e) } } } } // Retrofit API Service Interface interface LocationApiService { @POST("/api/user/location") suspend fun saveUserLocation(@Body request: LocationRequest): Response<LocationResponse> } // Data classes for API requests/responses data class LocationRequest(val location: String) data class LocationResponse(val updatedLocation: String)Update Shared ViewModel to Handle API Calls
Add a method to trigger the API save and update the LiveData once the call succeeds.import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.launch class SharedLocationViewModel : ViewModel() { val userLocation = MutableLiveData<String>() private lateinit var repository: LocationRepository fun initRepository(apiService: LocationApiService) { repository = LocationRepository(apiService) } // Call this to save location to server and update LiveData fun saveAndSyncLocation(location: String) { viewModelScope.launch { val result = repository.saveLocationToServer(location) if (result.isSuccess) { // Update LiveData with server's response userLocation.postValue(result.getOrNull()) } else { // Handle error (e.g., show toast) result.exceptionOrNull()?.printStackTrace() } } } }Observe Location in ActivityA
Similar to the simple scenario—watch theuserLocationLiveData to update the UI.viewModel.userLocation.observe(this) { updatedLocation -> tv_user_location.text = updatedLocation }Trigger Save from Your "ActivityC-like" Screen
When the user taps save, call the ViewModel's method to handle the API sync.btn_save_location.setOnClickListener { val newLocation = et_location.text.toString().trim() if (newLocation.isNotEmpty()) { viewModel.saveAndSyncLocation(newLocation) finish() } }
Key Notes:
- Using
viewModelScopeensures coroutines are canceled when the ViewModel is destroyed, preventing memory leaks. postValue()is used in the repository because we're updating LiveData from a background thread—usevalueonly from the main thread.- This pattern follows Android's recommended MVVM architecture, making your code scalable and easy to test.
内容的提问来源于stack exchange,提问作者Adil

