Is there a method that works like start fragment for result?
Solution 1:
All of the Fragments live inside Activities. Starting a Fragment for a result doesn't make much sense, because the Activity that houses it always has access to it, and vice versa. If the Fragment needs to pass on a result, it can access its Activity and set its result and finish it. In the case of swapping Fragments in a single Activity, well the Activity is still accessible by both Fragments, and all your message passing can simply go through the Activity.
Just remember that you always have communication between a Fragment and its Activity. Starting for and finishing with a result is the mechanism for communication between Activities - The Activities can then delegate any necessary information to their Fragments.
Solution 2:
If you wish, there are some methods for communication between Fragments,
setTargetFragment(Fragment fragment, int requestCode)
getTargetFragment()
getTargetRequestCode()
You can callback using these.
Fragment invoker = getTargetFragment();
if(invoker != null) {
invoker.callPublicMethod();
}
Solution 3:
Recently, Google has just added a new ability to FragmentManager
which made the FragmentManager
be able to act as a central store for fragment results. We can pass the data back and forth between Fragments easily.
You can out the blog post that I've made https://oozou.com/blog/starting-a-fragment-for-results-in-android-46
Starting fragment.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Use the Kotlin extension in the fragment-ktx artifact
setResultListener("requestKey") { key, bundle ->
// We use a String here, but any type that can be put in a Bundle is supported
val result = bundle.getString("bundleKey")
// Do something with the result...
}
}
A Fragment that we want the result back.
button.setOnClickListener {
val result = "result"
// Use the Kotlin extension in the fragment-ktx artifact
setResult("requestKey", bundleOf("bundleKey" to result))
}
The snippet is taken from Google's official documents. https://developer.android.com/training/basics/fragments/pass-data-between#kotlin
At the date of this answer written, this feature is still in alpha
state. You can try it out using this dependency.
androidx.fragment:fragment:1.3.0-alpha05
Solution 4:
We can simply share the same ViewModel between fragments
SharedViewModel
import android.arch.lifecycle.MutableLiveData
import android.arch.lifecycle.ViewModel
class SharedViewModel : ViewModel() {
val stringData: MutableLiveData<String> by lazy {
MutableLiveData<String>()
}
}
FirstFragment
import android.arch.lifecycle.Observer
import android.os.Bundle
import android.arch.lifecycle.ViewModelProviders
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
class FirstFragment : Fragment() {
private lateinit var sharedViewModel: SharedViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activity?.run {
sharedViewModel = ViewModelProviders.of(activity).get(SharedViewModel::class.java)
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_first, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
sharedViewModel.stringData.observe(this, Observer { dateString ->
// get the changed String
})
}
}
SecondFragment
import android.arch.lifecycle.ViewModelProviders
import android.os.Bundle
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGrou
class SecondFragment : Fragment() {
private lateinit var sharedViewModel: SharedViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activity?.run {
sharedViewModel = ViewModelProviders.of(activity).get(SharedViewModel::class.java)
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_first, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
changeString()
}
private fun changeString() {
sharedViewModel.stringData.value = "Test"
}
}