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