← Назад к вопросам

Как сохранить данные в Fragment для переиспользования

2.3 Middle🔥 141 комментариев
#Android компоненты#Работа с данными

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Сохранение данных во Fragment для повторного использования

Для сохранения данных во Fragment существует несколько подходов, выбор которых зависит от типа данных, их жизненного цикла и необходимости переиспользования. Вот основные методы, которые я применяю в разработке.

1. setRetainInstance (устаревший, но важно понимать)

В старых версиях Support Library использовался метод setRetainInstance(true), который сохранял экземпляр Fragment при изменении конфигурации (например, повороте экрана). Однако с переходом на AndroidX и архитектурные компоненты этот подход считается устаревшим (deprecated) и не рекомендуется к использованию.

// Устаревший подход - не используйте в новых проектах
class MyFragment : Fragment() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        retainInstance = true // Теперь deprecated
    }
}

2. Сохранение в Bundle (onSaveInstanceState)

Для сохранения простых данных при временном уничтожении Fragment (изменение конфигурации) используйте onSaveInstanceState:

class MyFragment : Fragment() {
    private var importantData: String = ""
    
    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        outState.putString("KEY_DATA", importantData)
    }
    
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
        if (savedInstanceState != null) {
            importantData = savedInstanceState.getString("KEY_DATA", "")
        }
    }
}

3. ViewModel с SavedStateHandle

ViewModel в сочетании с SavedStateHandle — это современный рекомендуемый подход для сохранения данных, которые должны пережить изменения конфигурации:

class MyViewModel(private val savedStateHandle: SavedStateHandle) : ViewModel() {
    companion object {
        private const val DATA_KEY = "important_data"
    }
    
    val importantData: LiveData<String> = savedStateHandle.getLiveData(DATA_KEY)
    
    fun saveData(data: String) {
        savedStateHandle.set(DATA_KEY, data)
    }
}

// Во Fragment
class MyFragment : Fragment() {
    private lateinit var viewModel: MyViewModel
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        viewModel = ViewModelProvider(this).get(MyViewModel::class.java)
        
        // Подписываемся на данные
        viewModel.importantData.observe(this) { data ->
            // Обновляем UI с сохранёнными данными
        }
    }
}

4. Shared ViewModel для обмена данными между Fragment

Для обмена данными между несколькими Fragment в пределах одной Activity используйте Shared ViewModel:

// ViewModel, привязанный к Activity
class SharedViewModel : ViewModel() {
    private val _sharedData = MutableLiveData<String>()
    val sharedData: LiveData<String> = _sharedData
    
    fun updateData(data: String) {
        _sharedData.value = data
    }
}

// Fragment A
class FragmentA : Fragment() {
    private val sharedViewModel: SharedViewModel by activityViewModels()
    
    fun saveData() {
        sharedViewModel.updateData("Данные из Fragment A")
    }
}

// Fragment B
class FragmentB : Fragment() {
    private val sharedViewModel: SharedViewModel by activityViewModels()
    
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        sharedViewModel.sharedData.observe(viewLifecycleOwner) { data ->
            // Используем данные из Fragment A
        }
    }
}

5. Ручное сохранение в аргументы

Данные можно передавать и сохранять через аргументы Fragment, что особенно полезно при создании экземпляров:

class MyFragment : Fragment() {
    companion object {
        private const val ARG_DATA = "arg_data"
        
        fun newInstance(data: String): MyFragment {
            val fragment = MyFragment()
            val args = Bundle().apply {
                putString(ARG_DATA, data)
            }
            fragment.arguments = args
            return fragment
        }
    }
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val savedData = arguments?.getString(ARG_DATA)
        // Используем сохранённые данные
    }
}

6. Постоянное хранение

Для долговременного сохранения данных используйте:

  • SharedPreferences для простых ключ-значение данных
  • Room Database для структурированных данных
  • DataStore как современную альтернативу SharedPreferences
// Пример с DataStore
class SettingsDataStore(private val context: Context) {
    private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")
    
    suspend fun saveImportantData(data: String) {
        context.dataStore.edit { preferences ->
            preferences[stringPreferencesKey("IMPORTANT_DATA")] = data
        }
    }
    
    val importantData: Flow<String> = context.dataStore.data
        .map { preferences ->
            preferences[stringPreferencesKey("IMPORTANT_DATA")] ?: ""
        }
}

Рекомендации по выбору метода

  1. Для UI-состояния (скролл-позиция, введённый текст) → ViewModel с SavedStateHandle
  2. Для обмена между FragmentShared ViewModel
  3. Для простых данных при поворотеonSaveInstanceState
  4. Для долговременного храненияRoom/DataStore/SharedPreferences
  5. Для передачи параметров при созданииАргументы Fragment

Ключевой принцип: данные должны переживать изменения конфигурации без потерь, но при этом не утекать память. ViewModel автоматически очищается при окончательном уничтожении Fragment, что предотвращает утечки памяти. Всегда учитывайте жизненный цикл Fragment (onCreate, onViewCreated, onDestroyView, onDestroy) при выборе стратегии сохранения данных.