ภาพรวมของ ViewModel (มุมมอง)
แนวคิดและการใช้งาน Jetpack Compose
คลาส ViewModel เป็นตัวเก็บสถานะระดับตรรกะทางธุรกิจหรือระดับหน้าจอ โดยจะแสดงสถานะต่อ UI และห่อหุ้มตรรกะทางธุรกิจที่เกี่ยวข้อง
ข้อดีหลักคือการแคชสถานะและเก็บสถานะไว้เมื่อมีการเปลี่ยนแปลงการกำหนดค่า ซึ่งหมายความว่า UI ไม่จำเป็นต้องดึงข้อมูลอีกครั้งเมื่อมีการนำทางระหว่างกิจกรรม หรือเมื่อมีการเปลี่ยนแปลงการกำหนดค่า เช่น เมื่อหมุนหน้าจอ
สิทธิประโยชน์ของ ViewModel
ทางเลือกแทน ViewModel คือคลาสธรรมดาที่เก็บข้อมูลที่คุณแสดงใน UI ซึ่งอาจกลายเป็นปัญหาเมื่อมีการนำทางระหว่างกิจกรรมหรือปลายทางการนำทาง เนื่องจากข้อมูลจะถูกทำลายหากคุณไม่จัดเก็บโดยใช้ กลไกการทำงานของสถานะอินสแตนซ์ที่บันทึกไว้ ViewModel มี API ที่สะดวกสำหรับการเก็บข้อมูลไว้ ซึ่งช่วยแก้ปัญหานี้ได้
ประโยชน์หลักของคลาส ViewModel มี 2 ข้อ ได้แก่
- ช่วยให้คุณเก็บสถานะ UI ไว้ได้
- ให้สิทธิ์เข้าถึงตรรกะทางธุรกิจ
ขอบเขต
เมื่อสร้างอินสแตนซ์ ViewModel คุณจะส่งออบเจ็กต์ที่ใช้
ViewModelStoreOwner อินเทอร์เฟซ ซึ่งอาจเป็นปลายทางการนำทาง กราฟการนำทาง กิจกรรม Fragment หรือประเภทอื่นๆ ที่ใช้ อินเทอร์เฟซ จากนั้น ViewModel จะมีขอบเขตเป็น Lifecycle ของ
ViewModelStoreOwner และจะยังคงอยู่ในหน่วยความจำจนกว่า ViewModelStoreOwner จะหายไปอย่างถาวร
คลาสหลายคลาสเป็นคลาสย่อยโดยตรงหรือโดยอ้อมของอินเทอร์เฟซ ViewModelStoreOwner คลาสย่อยโดยตรง ได้แก่
ComponentActivity, Fragment และ NavBackStackEntry
ดูรายการคลาสย่อยโดยอ้อมทั้งหมดได้ที่ข้อมูลอ้างอิง
ViewModelStoreOwner
ใช้ ViewModel
ต่อไปนี้เป็นตัวอย่างการใช้งาน ViewModel สำหรับหน้าจอที่อนุญาตให้ผู้ใช้ทอยลูกเต๋า
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
)
);
}
}
จากนั้นคุณจะเข้าถึง ViewModel จากกิจกรรมได้ดังนี้
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
});
}
}
แนะนำสำหรับคุณ
- หมายเหตุ: ข้อความลิงก์จะแสดงเมื่อ JavaScript ปิดอยู่
- ใช้โครูทีน Kotlin กับคอมโพเนนต์ที่รับรู้ถึงวงจรการทำงาน
- บันทึกสถานะ UI
- โหลดและแสดงข้อมูลแบบแบ่งหน้า