Android Kotlin ViewModel使用疑问:页面传值与ViewModel结合问题
Hey there! Nice work getting the Intent passing and basic ViewModel setup down—you're already halfway there. From what you shared, the most likely pain points right now are getting the Intent data into your ViewModel correctly (so it sticks through configuration changes like screen rotations) and making sure the random number logic works as expected. Let's break this into actionable steps with code examples.
Step 1: Create a ViewModel That Accepts Your Max Number
First, your ViewModel needs to know the upper limit from the Intent. Since ViewModels can't take constructor arguments directly without a factory, we'll make a custom ViewModelProvider.Factory to pass the max number in.
import androidx.lifecycle.ViewModel import kotlin.random.Random // ViewModel to hold the max number and handle random number generation class RandomNumberViewModel(private val maxNumber: Int) : ViewModel() { // Generate a random number between 0 and maxNumber (inclusive) fun getRandomNumber(): Int = Random.nextInt(0, maxNumber + 1) } // Factory class to pass the max number to the ViewModel class RandomNumberViewModelFactory(private val maxNumber: Int) : ViewModelProvider.Factory { override fun <T : ViewModel> create(modelClass: Class<T>): T { if (modelClass.isAssignableFrom(RandomNumberViewModel::class.java)) { @Suppress("UNCHECKED_CAST") return RandomNumberViewModel(maxNumber) as T } throw IllegalArgumentException("Unknown ViewModel class") } }
Step 2: Pass Intent Data to the ViewModel in Your Second Activity
In your second activity, grab the number from the Intent, then use the factory to initialize the ViewModel. This way, the max number is stored in the ViewModel and won't get lost if the screen rotates.
import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import androidx.lifecycle.ViewModelProvider import kotlinx.android.synthetic.main.activity_second.* class SecondActivity : AppCompatActivity() { private lateinit var viewModel: RandomNumberViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_second) // Fetch the max number from the Intent (default to 0 if extra is missing) val maxNumber = intent.getIntExtra("EXTRA_MAX_NUMBER", 0) // Initialize ViewModel with our custom factory viewModel = ViewModelProvider(this, RandomNumberViewModelFactory(maxNumber)) .get(RandomNumberViewModel::class.java) // Show a random number on first launch if (savedInstanceState == null) { updateRandomNumberDisplay() } // Add a button to generate a new random number (optional but user-friendly) refreshBtn.setOnClickListener { updateRandomNumberDisplay() } } private fun updateRandomNumberDisplay() { randomNumberTextView.text = viewModel.getRandomNumber().toString() } }
Step 3: Double-Check Your First Activity's Intent Setup
Make sure you're passing the number correctly from the first activity—use the same key (EXTRA_MAX_NUMBER) that we used in the second activity:
// Example from your first activity's increment/button logic incrementButton.setOnClickListener { val currentNumber = // Your incremented number (e.g., from a TextView or another ViewModel) val intent = Intent(this, SecondActivity::class.java).apply { putExtra("EXTRA_MAX_NUMBER", currentNumber) } startActivity(intent) }
Key Things to Remember
- Never generate the random number directly in the Activity: If you do, rotating the screen will re-run
onCreate()and generate a new number—defeating the purpose of using a ViewModel. - Use ViewModel Factories for parameterized ViewModels: ViewModels are meant to survive configuration changes, so passing data via a factory ensures the data stays with the ViewModel.
- Handle edge cases: If the user passes 0, the random number will always be 0—you might want to add a check in the first activity to ensure the number is at least 1 if that makes sense for your app.
内容的提问来源于stack exchange,提问作者Peter Weyand

