使用Android导航组件中的navigationUp传递数据/捆绑

时间:2019-03-08 07:37:56

标签: android android-fragments android-architecture-navigation android-safe-args

I found the question but does not have solution in code

当要进行后退/手动后退时,我想获取数据。我正在使用navigateUp()返回。如何将数据传递到上一个片段? navigateUp()没有任何工具可以将数据传递到上一个片段。甚至我都没有找到使用Safe Args的解决方案。它正在转发数据。我想在向后Frad B-> Frag A中找到

我的代码返回上一个片段

Navigation.findNavController(view).navigateUp()

enter image description here

我的问题是,如何获取上一个片段中的数据。我可以使用

从Frag B导航到Frag A

7 个答案:

答案 0 :(得分:2)

根据developer.android.com,对于要使用其活动范围共享数据ViewModel的片段,可以使用common。

以下是步骤:

  1. 创建将保留数据的视图模型:
class SharedViewModel : ViewModel() {
    val dataToShare = MutableLiveData<String>()

    fun updateData(data: String) {
        dataToShare.value = data
    }
}
  1. 观察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
        })
    }
}
  1. 更新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")
        }
    }
}

我希望答案会有所帮助。

答案 1 :(得分:1)

您应该使用静态变量/伴侣对象,因为它不是简单/精巧的体系结构,因此比共享视图模型更好。由于它并不简单,我认为这是最好的方法。

要从FragmentB导航到FragmentA

FragmentB:

MyOptional is <undefined>
MyOptional is abc

FragmentA:

isBackpressed = true
findNavController().navigateUp() 

答案 2 :(得分:0)

您可以NavigationResult库。基本上是startActivityForResult,但用于导航组件中的片段。

答案 3 :(得分:0)

您可以致电

findNavController().navigate(R.id.fragment1, args)

其中args是您的软件包。 在fragment1中,从参数中获取数据

答案 4 :(得分:0)

要在从一个目的地导航到另一个目的地时弹出目的地,请向关联的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)

答案 5 :(得分:0)

请使用官方androidx的组件。 setFragmentResultListener()setFragmentResult() 方法:

implementation "androidx.fragment:fragment-ktx:1.3.3"

干杯;)

答案 6 :(得分:-1)

您可以使用以下简单实现在 popBackStack()之后通过 Android导航组件传递数据。此方法基于官方Google documentation

您只需要使用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)
  1. 添加SharedViewModel类

    class SharedViewModel : ViewModel() {
        val sharedData = MutableLiveData<Any>()
    
        fun share(obj: Any) {
            sharedData.value = obj
        }
    }
    
  2. 添加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)
            }
        })
    }    
    }
    
  3. 添加Fragment1

    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
            }
        }
    }
    
  4. 添加Fragment2

    class Fragment2 : BaseFragment(){
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
    
            some_btn.setOnClickListener{
                popBackStackWithResult(AnyYourClass())
            }
        }            
    }
    

干杯;)