ViewModel için Kayıtlı Durum modülü Android Jetpack'in bir parçasıdır.
Şurada belirtildiği gibi:
Kullanıcı Arayüzü Durumlarını Kaydetme,
ViewModel
nesne işleyebilir
Bu nedenle, rotasyonlardaki durum konusunda endişelenmeniz gerekmez
durumlar olabilir. Ancak, sistem tarafından başlatılan bir işlemi gerçekleştirmeniz
ölüm durumunda SavedStateHandle
API'yi yedek olarak kullanmak isteyebilirsiniz.
Kullanıcı arayüzü durumu genellikle ViewModel
nesnelerde depolanır veya böyle bir duruma başvuruda bulunmaz
etkinlikleri olduğundan, onSaveInstanceState()
veya rememberSaveable
kullanmak için
kaydedilmiş durum modülünün
size yardımcı olabilir.
Bu modülü kullanırken ViewModel
nesne bir
SavedStateHandle
nesne
10-10 dakikadır. Bu nesne, bir anahtar/değer çiftinde
ve kaydedilen duruma nesne yazma ve alma. Bu değerler
işlem sistem tarafından sonlandırıldıktan sonra da devam eder ve kullanılabilir durumda kalır
üzerinden geçeceğim.
Kayıtlı durum, görev yığınınıza bağlıdır. Görev yığınınız kaybolursa durumu da ortadan kalkar. Bu durum, uygulama zorla durdurulurken, uygulamasını kullanabilir veya cihazı yeniden başlatabilirsiniz. Böyle durumlarda görev yığını kaybolur ve bilgileri kayıtlı durumda geri yükleyemezsiniz. İçinde Kullanıcı tarafından başlatılan kullanıcı arayüzü durumunu kapatma durumlarda, kaydedilen durum geri yüklenmez. İçinde sistem tarafından başlatılan gerçeğe dönüşebilir.
Kurulum
Parça 1.2.0 ile başlar
veya geçişli bağımlılığı
Etkinlik 1.1.0, kabul edebilirsiniz
ViewModel
için kurucu bağımsız değişken olarak bir SavedStateHandle
.
Kotlin
class SavedStateViewModel(private val state: SavedStateHandle) : ViewModel() { ... }
Java
public class SavedStateViewModel extends ViewModel { private SavedStateHandle state; public SavedStateViewModel(SavedStateHandle savedStateHandle) { state = savedStateHandle; } ... }
Daha sonra, başka herhangi bir ek olmadan ViewModel
yapılandırma. Varsayılan ViewModel
fabrika ayarı, uygun
ViewModel
cihazınıza SavedStateHandle
.
Kotlin
class MainFragment : Fragment() { val vm: SavedStateViewModel by viewModels() ... }
Java
class MainFragment extends Fragment { private SavedStateViewModel vm; public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { vm = new ViewModelProvider(this).get(SavedStateViewModel.class); ... } ... }
Bir özel rapor sağlarken
ViewModelProvider.Factory
örneğin, bu kodu genişleterek SavedStateHandle
kullanımını
AbstractSavedStateViewModelFactory
.
SavedStateHandle ile çalışma
SavedStateHandle
sınıfı, yazma ve
set()
ve get()
yöntemlerine göz atın.
SavedStateHandle
kullanıldığında, sorgu değeri süreç bitimine kadar korunur.
Böylece, kullanıcılara kampanya öncesinde ve sonrasında aynı filtrelenmiş veri kümesi gösterilir.
etkinlikleri veya parçaları manuel olarak kaydetmenize, geri yüklemenize,
ve bu değeri ViewModel
içine geri yönlendirir.
SavedStateHandle
, etkileşimde bulunurken bekleyebileceğiniz başka yöntemler de sunuyor
bir anahtar/değer eşlemesi ile:
contains(String key)
- Verilen anahtar için bir değer olup olmadığını kontrol eder.remove(String key)
- Belirli bir anahtarın değerini kaldırır.keys()
- İadelerSavedStateHandle
içindeki tüm anahtarlar.
Ayrıca, SavedStateHandle
etiketindeki değerleri bir
gözlenebilir veri tutucusu. Desteklenen türlerin listesi:
LiveData
SavedStateHandle
öğesinden bir içine sarmalanmış değerleri alın
LiveData
kullanılarak gözlemlenebilir
getLiveData()
.
Anahtarın değeri güncellendiğinde LiveData
yeni değeri alır. En sık
genellikle değer, kullanıcı etkileşimlerine bağlı olarak ayarlanır. Örneğin,
veri listesini filtreleyebilirsiniz. Bu güncellenen değer, daha sonra
Dönüştürme LiveData
.
Kotlin
class SavedStateViewModel(private val savedStateHandle: SavedStateHandle) : ViewModel() { val filteredData: LiveData<List<String>> = savedStateHandle.getLiveData<String>("query").switchMap { query -> repository.getFilteredData(query) } fun setQuery(query: String) { savedStateHandle["query"] = query } }
Java
public class SavedStateViewModel extends ViewModel { private SavedStateHandle savedStateHandle; public LiveData<List<String>> filteredData; public SavedStateViewModel(SavedStateHandle savedStateHandle) { this.savedStateHandle = savedStateHandle; LiveData<String> queryLiveData = savedStateHandle.getLiveData("query"); filteredData = Transformations.switchMap(queryLiveData, query -> { return repository.getFilteredData(query); }); } public void setQuery(String query) { savedStateHandle.set("query", query); } }
Durum Akışı
SavedStateHandle
öğesinden bir içine sarmalanmış değerleri alın
StateFlow
kullanılarak gözlemlenebilir
getStateFlow()
.
Anahtarın değerini güncellediğinizde StateFlow
yeni değeri alır. En sık
değeri kullanıcı etkileşimlerine bağlı olarak ayarlayabilirsiniz. Örneğin,
sorgu kullanabilirsiniz. Ardından, güncellenen bu değeri dönüştürebilirsiniz.
Akış operatörlerini kullanın.
Kotlin
class SavedStateViewModel(private val savedStateHandle: SavedStateHandle) : ViewModel() { val filteredData: StateFlow<List<String>> = savedStateHandle.getStateFlow<String>("query") .flatMapLatest { query -> repository.getFilteredData(query) } fun setQuery(query: String) { savedStateHandle["query"] = query } }
Deneysel Oluşturma durumu desteği
lifecycle-viewmodel-compose
yapısı, deneysel özellikleri sunar.
saveable
SavedStateHandle
ile Compose'un arasında birlikte çalışabilirliğe olanak tanıyan API'ler
Saver
böylece State
rememberSaveable
aracılığıyla kaydedebilir
özel bir Saver
ile SavedStateHandle
ile de kaydedilebilir.
Kotlin
class SavedStateViewModel(private val savedStateHandle: SavedStateHandle) : ViewModel() { var filteredData: List<String> by savedStateHandle.saveable { mutableStateOf(emptyList()) } fun setQuery(query: String) { withMutableSnapshot { filteredData += query } } }
Desteklenen türler
SavedStateHandle
içinde saklanan veriler
Bundle
ve
savedInstanceState
etkinliği veya parçayı ifade eder.
Doğrudan desteklenen türler
Varsayılan olarak, SavedStateHandle
üzerinde set()
ve get()
adlı kişileri
aşağıda gösterildiği gibi, Bundle
ile aynı veri türleri:
Tür/Sınıf desteği | Dizi desteği |
double |
double[] |
int |
int[] |
long |
long[] |
String |
String[] |
byte |
byte[] |
char |
char[] |
CharSequence |
CharSequence[] |
float |
float[] |
Parcelable |
Parcelable[] |
Serializable |
Serializable[] |
short |
short[] |
SparseArray |
|
Binder |
|
Bundle |
|
ArrayList |
|
Size (only in API 21+) |
|
SizeF (only in API 21+) |
Sınıf, yukarıdaki listede yer alan onlardan birini uzatmıyorsa,
@Parcelize
ekleyerek ayrıştırılabilir sınıfı
Kotlin ek açıklaması veya uygulama
Doğrudan Parcelable
.
Ayrıştırılamayan sınıfları kaydetme
Parcelable
veya Serializable
kullanmayan bir sınıf
uygulamak üzere değiştirilmiş bir sürümünü kullanıyorsanız
bu sınıfın bir örneğini doğrudan SavedStateHandle
sınıfına kaydedebilir.
Şununla başlayan:
Yaşam döngüsü 2.3.0-alpha03
SavedStateHandle
, kendi nesnenizi sağlayarak herhangi bir nesneyi kaydetmenize olanak tanır
sonraki adımları için şunları içerir:
Bundle
şunu kullanarak:
setSavedStateProvider()
yöntemidir. SavedStateRegistry.SavedStateProvider
tek bir kodu tanımlayan bir
saveState()
yöntemi, kaydetmek istediğiniz durumu içeren bir Bundle
döndürür. Zaman
SavedStateHandle
, durumunu kaydetmeye hazır. Çağrı: saveState()
Bundle
öğesini SavedStateProvider
kaynağından alır ve
İlişkili anahtar için Bundle
.
Kamera uygulamasından görüntü isteyen bir uygulamaya örnek verelim.
ACTION_IMAGE_CAPTURE
(kameranın bu bilgiyi saklaması gereken yer için geçici bir dosya
görüntüsüdür. TempFileViewModel
, bu önerinin
geçici bir dosyadır.
Kotlin
class TempFileViewModel : ViewModel() { private var tempFile: File? = null fun createOrGetTempFile(): File { return tempFile ?: File.createTempFile("temp", null).also { tempFile = it } } }
Java
class TempFileViewModel extends ViewModel { private File tempFile = null; public TempFileViewModel() { } @NonNull public File createOrGetTempFile() { if (tempFile == null) { tempFile = File.createTempFile("temp", null); } return tempFile; } }
Etkinliğin işlemi sonlandırılırsa geçici dosyanın kaybolmadığından emin olmak için
ve daha sonra geri yüklenen TempFileViewModel
, SavedStateHandle
öğesini kullanarak şu işlemleri yapabilir:
kullanmaya devam etmesini sağlar. TempFileViewModel
uygulamasının verilerini kaydetmesine izin vermek için şunu uygula:
SavedStateProvider
ve şurada sağlayıcı olarak ayarlandı: SavedStateHandle
ViewModel
:
Kotlin
private fun File.saveTempFile() = bundleOf("path", absolutePath) class TempFileViewModel(savedStateHandle: SavedStateHandle) : ViewModel() { private var tempFile: File? = null init { savedStateHandle.setSavedStateProvider("temp_file") { // saveState() if (tempFile != null) { tempFile.saveTempFile() } else { Bundle() } } } fun createOrGetTempFile(): File { return tempFile ?: File.createTempFile("temp", null).also { tempFile = it } } }
Java
class TempFileViewModel extends ViewModel { private File tempFile = null; public TempFileViewModel(SavedStateHandle savedStateHandle) { savedStateHandle.setSavedStateProvider("temp_file", new TempFileSavedStateProvider()); } @NonNull public File createOrGetTempFile() { if (tempFile == null) { tempFile = File.createTempFile("temp", null); } return tempFile; } private class TempFileSavedStateProvider implements SavedStateRegistry.SavedStateProvider { @NonNull @Override public Bundle saveState() { Bundle bundle = new Bundle(); if (tempFile != null) { bundle.putString("path", tempFile.getAbsolutePath()); } return bundle; } } }
Kullanıcı geri döndüğünde File
verilerini geri yüklemek için temp_file
öğesini alın
SavedStateHandle
arasında Bundle
. Bu, Bundle
tarafından sağlanan aynı
Mutlak yolu içeren saveTempFile()
. Bu durumda mutlak yol,
yeni bir File
örneği oluşturmak için kullanılır.
Kotlin
private fun File.saveTempFile() = bundleOf("path", absolutePath) private fun Bundle.restoreTempFile() = if (containsKey("path")) { File(getString("path")) } else { null } class TempFileViewModel(savedStateHandle: SavedStateHandle) : ViewModel() { private var tempFile: File? = null init { val tempFileBundle = savedStateHandle.get<Bundle>("temp_file") if (tempFileBundle != null) { tempFile = tempFileBundle.restoreTempFile() } savedStateHandle.setSavedStateProvider("temp_file") { // saveState() if (tempFile != null) { tempFile.saveTempFile() } else { Bundle() } } } fun createOrGetTempFile(): File { return tempFile ?: File.createTempFile("temp", null).also { tempFile = it } } }
Java
class TempFileViewModel extends ViewModel { private File tempFile = null; public TempFileViewModel(SavedStateHandle savedStateHandle) { Bundle tempFileBundle = savedStateHandle.get("temp_file"); if (tempFileBundle != null) { tempFile = TempFileSavedStateProvider.restoreTempFile(tempFileBundle); } savedStateHandle.setSavedStateProvider("temp_file", new TempFileSavedStateProvider()); } @NonNull public File createOrGetTempFile() { if (tempFile == null) { tempFile = File.createTempFile("temp", null); } return tempFile; } private class TempFileSavedStateProvider implements SavedStateRegistry.SavedStateProvider { @NonNull @Override public Bundle saveState() { Bundle bundle = new Bundle(); if (tempFile != null) { bundle.putString("path", tempFile.getAbsolutePath()); } return bundle; } @Nullable private static File restoreTempFile(Bundle bundle) { if (bundle.containsKey("path") { return File(bundle.getString("path")); } return null; } } }
Testlerde SavedStateHandle
Bağımlılık olarak SavedStateHandle
alan bir ViewModel
test etmek için
gereken ve başarılı test değerlerine sahip yeni bir SavedStateHandle
örneği
bunu test ettiğiniz ViewModel
örneğine gönderebilirsiniz.
Kotlin
class MyViewModelTest { private lateinit var viewModel: MyViewModel @Before fun setup() { val savedState = SavedStateHandle(mapOf("someIdArg" to testId)) viewModel = MyViewModel(savedState = savedState) } }
Ek kaynaklar
ViewModel
için Kayıtlı Durum modülü hakkında daha fazla bilgi için
inceleyebilirsiniz.
Codelab'ler
ziyaret edin.Sizin için önerilenler
- Not: JavaScript kapalıyken bağlantı metni gösterilir
- Kullanıcı arayüzü durumlarını kaydet
- Gözlemlenebilir veri nesneleriyle çalışma
- Bağımlılıkları olan ViewModel'ler oluşturma