Ringkasan ViewModel (Tampilan)

Konsep dan implementasi Jetpack Compose

Class ViewModel adalah pemegang logika bisnis atau status tingkat layar holder. Class ini mengekspos status ke UI dan mengenkapsulasi logika bisnis terkait. Keuntungan utamanya adalah melakukan cache status dan mempertahankannya melalui perubahan konfigurasi. Artinya, UI Anda tidak perlu mengambil data lagi saat bernavigasi di antara aktivitas, atau mengikuti perubahan konfigurasi, seperti saat memutar layar.

Manfaat ViewModel

Alternatif untuk ViewModel adalah class biasa yang menyimpan data yang ditampilkan di UI. Hal ini dapat menjadi masalah saat bernavigasi di antara aktivitas atau tujuan Navigation. Tindakan ini akan menghapus data tersebut jika Anda tidak menyimpannya menggunakan mekanisme status instance penyimpanan. ViewModel menyediakan API yang praktis untuk persistensi data yang menyelesaikan masalah ini.

Manfaat utama class ViewModel pada dasarnya ada dua:

  • Memungkinkan Anda mempertahankan status UI.
  • Menyediakan akses ke logika bisnis.

Cakupan

Saat membuat instance ViewModel, Anda akan meneruskan objek yang mengimplementasikan antarmuka ViewModelStoreOwner. Ini dapat berupa tujuan Navigation , grafik Navigation, aktivitas, fragmen, atau jenis lain yang mengimplementasikan antarmuka. ViewModel Anda kemudian tercakup ke Lifecycle ViewModelStoreOwner. ViewModel tetap ada dalam memori hingga ViewModelStoreOwner-nya hilang secara permanen.

Rentang class adalah subclass langsung atau tidak langsung dari antarmuka ViewModelStoreOwner. Subclass langsung adalah ComponentActivity, Fragment, dan NavBackStackEntry. Untuk mengetahui daftar lengkap subclass tidak langsung, lihat referensi ViewModelStoreOwner.

Mengimplementasikan ViewModel

Berikut adalah contoh implementasi ViewModel untuk layar yang memungkinkan pengguna melempar dadu.

Kotlin

data class DiceUiState(
    val firstDieValue: Int? = null,
    val secondDieValue: Int? = null,
    val numberOfRolls: Int = 0,
)

class DiceRollViewModel : ViewModel() {

    // Expose screen UI state
    private val _uiState = MutableStateFlow(DiceUiState())
    val uiState: StateFlow<DiceUiState> = _uiState.asStateFlow()

    // Handle business logic
    fun rollDice() {
        _uiState.update { currentState ->
            currentState.copy(
                firstDieValue = Random.nextInt(from = 1, until = 7),
                secondDieValue = Random.nextInt(from = 1, until = 7),
                numberOfRolls = currentState.numberOfRolls + 1,
            )
        }
    }
}

Java

public class DiceUiState {
    private final Integer firstDieValue;
    private final Integer secondDieValue;
    private final int numberOfRolls;

    // ...
}

public class DiceRollViewModel extends ViewModel {

    private final MutableLiveData<DiceUiState> uiState =
        new MutableLiveData(new DiceUiState(null, null, 0));
    public LiveData<DiceUiState> getUiState() {
        return uiState;
    }

    public void rollDice() {
        Random random = new Random();
        uiState.setValue(
            new DiceUiState(
                random.nextInt(7) + 1,
                random.nextInt(7) + 1,
                uiState.getValue().getNumberOfRolls() + 1
            )
        );
    }
}

Anda kemudian dapat mengakses ViewModel dari aktivitas dengan cara sebagai berikut:

Kotlin

import androidx.activity.viewModels

class DiceRollActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        // Create a ViewModel the first time the system calls an activity's onCreate() method.
        // Re-created activities receive the same DiceRollViewModel instance created by the first activity.

        // Use the 'by viewModels()' Kotlin property delegate
        // from the activity-ktx artifact
        val viewModel: DiceRollViewModel by viewModels()
        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                viewModel.uiState.collect {
                    // Update UI elements
                }
            }
        }
    }
}

Java

public class MyActivity extends AppCompatActivity {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Create a ViewModel the first time the system calls an activity's onCreate() method.
        // Re-created activities receive the same MyViewModel instance created by the first activity.
        DiceRollViewModel model = new ViewModelProvider(this).get(DiceRollViewModel.class);
        model.getUiState().observe(this, uiState -> {
            // update UI
        });
    }
}