ViewModel के लिए सेव किया गया स्टेट मॉड्यूल Android Jetpack का हिस्सा है.

जैसा कि इसमें बताया गया है यूज़र इंटरफ़ेस (यूआई) की स्थितियों को सेव करना, ViewModel ऑब्जेक्ट हैंडल कर सकते हैं कॉन्फ़िगरेशन बदल जाता है, इसलिए आपको रोटेशन की स्थिति की चिंता करने की आवश्यकता नहीं है या अन्य मामलों में. हालांकि, अगर आपको सिस्टम से शुरू की गई प्रोसेस को मैनेज करना हो, तो मौत हो, तो हो सकता है कि आप बैकअप के रूप में SavedStateHandle API का इस्तेमाल करना चाहें.

यूज़र इंटरफ़ेस (यूआई) की स्थिति को आम तौर पर ViewModel ऑब्जेक्ट में सेव या रेफ़र किया जाता है, न कि गतिविधियों की वजह से, onSaveInstanceState() या rememberSaveable का इस्तेमाल करने के लिए बॉयलरप्लेट जो सहेजा गया स्टेट मॉड्यूल आपके लिए संभाल सकता है.

इस मॉड्यूल का इस्तेमाल करने पर, ViewModel ऑब्जेक्ट को SavedStateHandle ऑब्जेक्ट इसके कंस्ट्रक्टर की मदद से ऐसा करता है. यह ऑब्जेक्ट एक की-वैल्यू मैप है. इससे आपको सेव की गई स्थिति में ऑब्जेक्ट लिखने और उसे वापस लाने के लिए. ये वैल्यू सिस्टम से प्रोसेस खत्म हो जाने के बाद भी बना रहता है एक ही ऑब्जेक्ट से होकर गुज़रता है.

सेव की गई स्थिति, आपके टास्क स्टैक से जुड़ी है. अगर आपका टास्क स्टैक हट जाता है, तो राज्य से बाहर हो जाता है. ऐसा तब हो सकता है, जब किसी ऐप्लिकेशन को ज़बरदस्ती रोका जाता है और हाल ही के मेन्यू से ऐप्लिकेशन खोलें या डिवाइस को फिर से चालू करें. ऐसे मामलों में, टास्क स्टैक हट जाता है और सेव की गई स्थिति में जानकारी को वापस नहीं लाया जा सकता. तय सीमा में उपयोगकर्ता की ओर से शुरू की गई यूज़र इंटरफ़ेस (यूआई) स्थिति खारिज करना तो सेव की गई स्थिति वापस नहीं आती. तय सीमा में सिस्टम से शुरू किया गया कोई बात नहीं.

सेटअप

फ़्रैगमेंट 1.2.0 से शुरू करना या इसकी ट्रांज़िटिव डिपेंडेंसी गतिविधि 1.1.0, आपके पास इन चीज़ों को स्वीकार करने का विकल्प है आपके ViewModel में निर्माता तर्क के रूप में SavedStateHandle.

Kotlin

class SavedStateViewModel(private val state: SavedStateHandle) : ViewModel() { ... }

Java

public class SavedStateViewModel extends ViewModel {
    private SavedStateHandle state;

    public SavedStateViewModel(SavedStateHandle savedStateHandle) {
        state = savedStateHandle;
    }

    ...
}

इसके बाद, अपने ViewModel का इंस्टेंस, बिना किसी अतिरिक्त यूआरएल के वापस लाया जा सकता है कॉन्फ़िगरेशन. डिफ़ॉल्ट ViewModel फ़ैक्ट्री सही जानकारी देती है आपके ViewModel में 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);

        ...


    }

    ...
}

कस्टम पैरामीटर बनाते समय ViewModelProvider.Factory उदाहरण के लिए, SavedStateHandle AbstractSavedStateViewModelFactory.

SafeStateHandle के साथ काम करना

SavedStateHandle क्लास एक की-वैल्यू मैप है, जिसकी मदद से के द्वारा सहेजी गई स्थिति में और उससे डेटा set() और get() तरीकों का इस्तेमाल करना होगा.

SavedStateHandle का इस्तेमाल करने पर, क्वेरी की वैल्यू तब तक बनी रहती है, जब तक प्रोसेस पूरी नहीं हो जाती, यह पक्का करना कि उपयोगकर्ता को पहले और बाद में फ़िल्टर किए गए डेटा का एक ही सेट दिखे मनोरंजन के लिए, मैन्युअल तौर पर सेव, पहले जैसा करने की ज़रूरत नहीं होती. और उस वैल्यू को वापस ViewModel पर भेज देता है.

SavedStateHandle में अन्य तरीके भी हैं, जिनका इस्तेमाल इंटरैक्ट करते समय किया जा सकता है की-वैल्यू मैप की मदद से:

  • contains(String key) से यह जांचता है कि दी गई कुंजी के लिए कोई वैल्यू है या नहीं.
  • remove(String key) से दी गई कुंजी से वैल्यू हटाता है.
  • keys() - लौटाए गए प्रॉडक्ट SavedStateHandle में मौजूद सभी कुंजियां.

इसके अलावा, SavedStateHandle से वैल्यू फिर से पाने के लिए इनका इस्तेमाल किया जा सकता है मॉनिटर किया जा सकने वाला डेटा होल्डर. इस्तेमाल किए जा सकने वाले टाइप की सूची यहां दी गई है:

LiveData

SavedStateHandle से वे मान वापस पाएं जिन्हें LiveData का इस्तेमाल करके मॉनिटर किया जा सकता है getLiveData(). कुंजी की वैल्यू अपडेट होने पर, LiveData को नई वैल्यू मिलती है. ज़्यादातर अक्सर, मान को उपयोगकर्ता इंटरैक्शन के कारण सेट किया जाता है, जैसे डेटा की सूची फ़िल्टर करें. इसके बाद, अपडेट की गई इस वैल्यू का इस्तेमाल इन कामों के लिए किया जा सकता है 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);
    }
}

स्टेटफ़्लो

SavedStateHandle से वे मान वापस पाएं जिन्हें StateFlow का इस्तेमाल करके मॉनिटर किया जा सकता है getStateFlow(). कुंजी की वैल्यू अपडेट करने पर, StateFlow को नई वैल्यू मिलती है. ज़्यादातर अक्सर, उपयोगकर्ता इंटरैक्शन के कारण मान सेट कर सकते हैं, जैसे दर्ज क्वेरी का इस्तेमाल करें. इसके बाद, अपडेट की गई इस वैल्यू को बदला जा सकता है दूसरे फ़्लो ऑपरेटर का इस्तेमाल करके.

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
    }
}

एक्सपेरिमेंटल कंपोज़ की सुविधा की स्थिति

lifecycle-viewmodel-compose आर्टफ़ैक्ट, प्रयोग के तौर पर उपलब्ध कराता है saveable ऐसे एपीआई जो SavedStateHandle और Compose के बीच इंटरऑपरेबिलिटी (दूसरे सिस्टम के साथ काम करने की सुविधा) की अनुमति देते हैं Saver ताकि कोई भी State rememberSaveable के ज़रिए सेव कर सकते हैं पसंद के मुताबिक बनाए गए Saver के साथ, SavedStateHandle के साथ भी सेव किया जा सकता है.

Kotlin

class SavedStateViewModel(private val savedStateHandle: SavedStateHandle) : ViewModel() {

    var filteredData: List<String> by savedStateHandle.saveable {
        mutableStateOf(emptyList())
    }

    fun setQuery(query: String) {
        withMutableSnapshot {
            filteredData += query
        }
    }
}

काम करने वाली फ़ाइल के टाइप

SavedStateHandle में रखे गए डेटा को Bundle के साथ ही, अन्य savedInstanceState गतिविधि या फ़्रैगमेंट के लिए.

सीधे तौर पर काम करने वाले टाइप

डिफ़ॉल्ट रूप से, आप set() और get() को SavedStateHandle पर कॉल करके Bundle जैसा डेटा टाइप, जैसा कि नीचे दिखाया गया है:

टाइप/क्लास सहायता कलेक्शन से जुड़ी सहायता
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+)

यदि कक्षा ऊपर दी गई सूची में से एक का विस्तार नहीं करती है, तो @Parcelize को जोड़कर पार्स किया जा सकने वाला क्लास Kotlin एनोटेशन या लागू करना Parcelable सीधे.

पार्स नहीं की जा सकने वाली क्लास सेव की जा रही हैं

अगर कोई क्लास Parcelable या Serializable को लागू नहीं करती और में बदलाव कर दिया है, तो उस क्लास के इंस्टेंस को सीधे SavedStateHandle में सेव करें.

इससे शुरुआत लाइफ़साइकल 2.3.0-alpha03, SavedStateHandle आपको अपना खुद का ऑब्जेक्ट देकर किसी भी ऑब्जेक्ट को सेव करने की अनुमति देता है आपका ऑब्जेक्ट को Bundle का इस्तेमाल setSavedStateProvider() तरीका. SavedStateRegistry.SavedStateProvider एक ऐसा इंटरफ़ेस है जो saveState() तरीका, जो Bundle वाला नतीजा दिखाता है, जिसमें वह स्थिति होती है जिसे आपको सेव करना है. टास्क कब शुरू होगा SavedStateHandle अपनी स्थिति सेव करने के लिए तैयार है और यह saveState() को कॉल करता है SavedStateProvider से Bundle को वापस पाने के लिए, और जुड़ी हुई कुंजी के लिए Bundle.

किसी ऐसे ऐप्लिकेशन के उदाहरण पर विचार करें जो Camera ऐप्लिकेशन से इमेज का अनुरोध करता है. इसके लिए, ACTION_IMAGE_CAPTURE इंटेंट, एक अस्थायी फ़ाइल पास कर रहा है, जहां कैमरे को इमेज. TempFileViewModel, लॉजिक बनाने के लिए लॉजिक को इकट्ठा करता है अस्थायी फ़ाइल.

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;
    }
}

यह पक्का करने के लिए कि गतिविधि की प्रोसेस बंद हो जाने पर अस्थायी फ़ाइल खो न जाए और बाद में बहाल कर दिया जाएगा, TempFileViewModel इन कामों के लिए SavedStateHandle का इस्तेमाल कर सकता है वह उस डेटा को सेव करके रखे. TempFileViewModel अपना डेटा सेव कर सके, इसके लिए लागू करें SavedStateProvider और इसे सेवा देने वाली कंपनी के तौर पर, इस तारीख के 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;
        }
    }
}

उपयोगकर्ता के वापस आने पर, File का डेटा वापस लाने के लिए, temp_file को वापस पाएं SavedStateHandle से Bundle. यह वही Bundle है जो इन्होंने उपलब्ध कराया है saveTempFile(), जिसमें ऐब्सलूट पाथ शामिल है. ऐब्सलूट पाथ से ऐसा हो सकता है नया File इंस्टैंशिएट करने के लिए इस्तेमाल किया जाएगा.

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;
        }
    }
}

टेस्ट मेंSaveStateHandle

SavedStateHandle को डिपेंडेंसी के तौर पर इस्तेमाल करने वाले ViewModel की जांच करने के लिए, बनाएं SavedStateHandle का एक नया इंस्टेंस, जिसकी ज़रूरी टेस्ट वैल्यू के साथ इसे पास किया गया है इसे ViewModel इंस्टेंस पर टेस्ट करें.

Kotlin

class MyViewModelTest {

    private lateinit var viewModel: MyViewModel

    @Before
    fun setup() {
        val savedState = SavedStateHandle(mapOf("someIdArg" to testId))
        viewModel = MyViewModel(savedState = savedState)
    }
}

अन्य संसाधन

ViewModel के लिए सेव की गई स्थिति वाले मॉड्यूल के बारे में ज़्यादा जानकारी के लिए, देखें इन संसाधनों को देखें.

कोड लैब