Передайте данные / пакет, используя navigateUp в Android Navigation Component
Я нашел вопрос, но не нашел решения в коде
Я хочу получить данные, когда происходит обратное нажатие / ручное возвращение. я использую navigateUp()
идти обратно. Как я могу передать данные в предыдущий фрагмент? navigateUp()
не имеет возможности передавать данные в предыдущий фрагмент. Даже я не нашел решения с помощью Safe Args. Это передача данных вперед. Я хочу иметь в обратном Frad B -> Frag A.
Мой код, чтобы вернуться к предыдущему фрагменту
Navigation.findNavController(view).navigateUp()
У меня вопрос, как я могу получить данные в предыдущем фрагменте. Я могу перейти к Frag A из Frag B, используя
7 ответов
Согласно developer.android.com, вы можете использовать общие для фрагментов, где вы хотите поделиться данными ViewModel, используя их область действия.
Вот шаги:
- Создайте модель представления, которая будет хранить данные:
class SharedViewModel : ViewModel() {
val dataToShare = MutableLiveData<String>()
fun updateData(data: String) {
dataToShare.value = data
}
}
- Наблюдайте за изменениями данных в Fragment1:
class Fragment1 : Fragment() {
private lateinit var viewModel: SharedViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel = ViewModelProviders.of(activity!!).get(SharedViewModel::class.java)
model.dataToShare.observe(this, Observer<String> { dataFromFragment2 ->
// do something with data
})
}
}
- Обновить данные в
Fragment2
и если вы обрабатываете навигацию правильно, теперь вы сможете получать изменения данных наFragment1
:
class Fragment2 : Fragment() {
private lateinit var viewModel: SharedViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel = ViewModelProviders.of(activity!!).get(SharedViewModel::class.java)
updateDataButton.setOnClickListener { v ->
viewModel.updateData("New data for fragment1")
}
}
}
Надеюсь, ответ поможет.
Вы можете использовать методы setFragmentResultListener () и setFragmentResult() из androidx:
implementation "androidx.fragment:fragment-ktx:1.3.3"
Ваше здоровье ;)
Вы можете использовать библиотеку NavigationResult. В основном этоstartActivityForResult
но для компонента "Фрагменты в навигации".
Чтобы показывать пункты назначения при переходе от одного пункта назначения к другому, добавьте
app:popUpTo
атрибут связанного
<action>
элемент. Чтобы перейти от fargment2 к Fragment1 с аргументами, укажите в графе навигации
action
фрагмента вызывающего абонента и
arguments
целевого фрагмента:
<fragment
android:id="@+id/fragment2"
android:name="com.example.myapplication.Fragment2"
android:label="fragment_2"
tools:layout="@layout/fragment_2">
<action
android:id="@+id/action_2_to_1"
app:destination="@id/fragment1"
app:popUpTo="@+id/fragment1"/>
</fragment>
<fragment
android:id="@+id/fragment1"
android:name="com.example.myapplication.Fragment1"
android:label="fragment_1"
tools:layout="@layout/fragment_1">
<argument
android:name="someArgument"
app:argType="string"
app:nullable="false"
android:defaultValue="Hello Word"/>
</fragment>
В вашем классе Fragment2 вы вызываете свое действие и передаете свой аргумент:
val action = Fragment2Directions.action2To1("MY_STRING_ARGUMENT")
findNavController().navigate(action)
Вы должны использовать статические переменные / сопутствующие объекты, потому что это лучше, чем общая модель просмотра, поскольку это не простая / красивая архитектура. Поскольку это непросто, я думаю, что это лучший способ.
Переход от фрагмента B к фрагменту A
Фрагмент B:
isBackpressed = true
findNavController().navigateUp()
Фрагмент A:
onViewCreated() {
// todo
if(isBackpressed) {
isBackpressed = false
// do whatever you want
}
}
Вы можете просто позвонить
findNavController().navigate(R.id.fragment1, args)
где args - ваш пакет. Во фрагменте 1 выберите данные из аргументов
Вы можете использовать следующую простую реализацию для передачи данных после popBackStack() с помощью компонента навигации Android. Этот подход основан на официальной документации Google.
Вам просто нужно расширить свои фрагменты с помощью BaseFragment и использовать следующие методы:
//to start Fragment2 for result
startFragmentForResult(actionId: Int)
//to perform pop back stack in Fragment2
popBackStackWithResult(result: Any)
//to observe your result in Fragment1
onFragmentResult(result: Any)
Добавить класс SharedViewModel
class SharedViewModel : ViewModel() { val sharedData = MutableLiveData<Any>() fun share(obj: Any) { sharedData.value = obj } }
Добавить класс BaseFragment
import androidx.fragment.app.Fragment abstract class BaseFragment : Fragment() { protected var rootView: View? = null private var sharedViewModel: SharedViewModel? = null override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { if (rootView == null) { rootView = inflater.inflate(getLayoutId(), container, false) initSharedViewModel() } return rootView } abstract fun getLayoutId() open fun onFragmentResult(result: Any){ //TODO implement in descendants } protected fun startFragmentForResult(actionId: Int){ findNavController().navigate(actionId) } protected fun popBackStackWithResult(result: Any){ findNavController().popBackStack() sharedViewModel?.share(result) } private fun initSharedViewModel() { sharedViewModel = ViewModelProvider(activity!!).get(SharedViewModel::class.java) sharedViewModel?.sharedData?.observe(activity!!, object : Observer<Any> { override fun onChanged(params: Any) { onFragmentResult(params) } }) } }
Добавить фрагмент1
class Fragment1 : BaseFragment(){ override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) some_btn.setOnClickListener{ startFragmentForResult(R.id.action_fragment1_to_fragment2) } } override fun onFragmentResult(result: Any) { if(result is AnyYourClass){ //PERFECT! DO SOMETHING WITH YOUR RESULT } } }
Добавить фрагмент 2
class Fragment2 : BaseFragment(){ override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) some_btn.setOnClickListener{ popBackStackWithResult(AnyYourClass()) } } }
Ура;)