是否有一种方法可以像结果的起始片段一样工作?

CAC*_*lan 81 android android-fragments android-3.0-honeycomb

我目前在叠加层中有一个片段.这是用于登录该服务.在手机应用程序中,我想在叠加层中显示的每个步骤都是他们自己的屏幕和活动.登录过程有3个部分,每个部分都有自己的活动,使用startActivityForResult()调用.

现在我想使用片段和叠加层做同样的事情.叠加层将显示与每个活动相对应的片段.问题是这些片段托管在Honeycomb API中的一个活动中.我可以让第一个片段工作,但后来我需要startActivityForResult(),这是不可能的.是否有类似于startFragmentForResult()的内容,我可以在其中启动一个新片段,当它完成后,它会将结果返回到前一个片段?

nag*_*ya0 57

如果您愿意,可以使用一些片段之间的通信方法,

setTargetFragment(Fragment fragment, int requestCode)
getTargetFragment()
getTargetRequestCode()
Run Code Online (Sandbox Code Playgroud)

您可以使用这些回调.

Fragment invoker = getTargetFragment();
if(invoker != null) {
    invoker.callPublicMethod();
}
Run Code Online (Sandbox Code Playgroud)

  • 即使更换片段,这是否也能正常工作? (9认同)
  • 迄今为止最佳解决方案 当有一个Activity和一堆片段时,工作得很好,试图找到正确的片段通知将是一场噩梦.谢谢 (2认同)

Lef*_*nia 52

所有碎片都存在于活动中.为结果启动片段没有多大意义,因为包含它的Activity始终可以访问它,反之亦然.如果Fragment需要传递结果,它可以访问其Activity并设置其结果并完成它.在单个Activity中交换Fragments的情况下,两个Frags仍然可以访问Activity,并且所有消息传递都可以通过Activity完成.

请记住,您始终在片段及其活动之间进行通信.开始和结束的结果是活动之间的通信机制 - 活动可以将任何必要的信息委托给它们的碎片.

  • 另外,当从另一个片段加载一个片段时,您可以设置目标片段并在需要时回调父片段的`onActivityResult`方法. (8认同)
  • 你的答案是不完整的,片段正在使用像活动一样的生命周期.所以,我们不能通过方法来传递参数,但我们应该使用bundle来传递值.即使片段在某处设置了值,我们也需要知道他何时结束.以前的片段在开始/恢复时是否会获得值?这是一个想法.但是没有适当的方法来存储值,片段可以由多个其他片段/活动调用. (2认同)
  • 好吧,调用“结果的起始片段”是有意义的,因为它会提供更大的灵活性 - >为什么作为子片段的片段应该知道其父片段?对于片段来说,无论他处于哪个活动中,只完成其工作并返回结果都不会更干净。特别是在单一活动应用程序的上下文中。 (2认同)

Boo*_*tak 19

最近,Google 刚刚添加了一项新功能FragmentManager,使其FragmentManager能够充当片段结果的中央存储。我们可以轻松地在 Fragment 之间来回传递数据。

您可以发布我制作的博客文章https://oozou.com/blog/starting-a-fragment-for-results-in-android-46

开始片段。

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...
    }
}
Run Code Online (Sandbox Code Playgroud)

我们想要返回结果的 Fragment。

button.setOnClickListener {
    val result = "result"
    // Use the Kotlin extension in the fragment-ktx artifact
    setResult("requestKey", bundleOf("bundleKey" to result))
}
Run Code Online (Sandbox Code Playgroud)

该片段取自 Google 的官方文档。 https://developer.android.com/training/basics/fragments/pass-data-between#kotlin

在撰写此答案之日,此功能仍处于alpha状态。您可以使用此依赖项进行尝试。

androidx.fragment:fragment:1.3.0-alpha05
Run Code Online (Sandbox Code Playgroud)


Lev*_*yan 11

我们可以简单地在片段之间共享相同的ViewModel

共享视图模型

import android.arch.lifecycle.MutableLiveData
import android.arch.lifecycle.ViewModel

class SharedViewModel : ViewModel() {

    val stringData: MutableLiveData<String> by lazy {
        MutableLiveData<String>()
    }

}
Run Code Online (Sandbox Code Playgroud)

第一个片段

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

    }

}
Run Code Online (Sandbox Code Playgroud)

第二个片段

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

}
Run Code Online (Sandbox Code Playgroud)

  • 嗨 Levon,我认为上面的代码不会共享相同的视图模型实例。您正在为 ViewModelProviders.of(this).get(SharedViewModel::class.java) 传递 this(fragment)。这将为片段创建两个单独的实例。您需要传递活动 ViewModelProviders.of(activity).get(SharedViewModel::class.java) (3认同)

Ali*_*aka 5

我的 2 美分。

我通过使用隐藏和显示/添加(现有/新)将旧片段与新片段交换来在片段之间切换。所以这个答案适用于像我一样使用片段的开发人员。

然后我使用该onHiddenChanged方法知道旧片段从新片段切换回。请参阅下面的代码。

在离开新片段之前,我在一个全局参数中设置了一个结果以供旧片段查询。这是一个非常幼稚的解决方案。

@Override
public void onHiddenChanged(boolean hidden) {
    super.onHiddenChanged(hidden);
    if (hidden) return;
    Result result = Result.getAndReset();
    if (result == Result.Refresh) {
        refresh();
    }
}

public enum Result {
    Refresh;

    private static Result RESULT;

    public static void set(Result result) {
        if (RESULT == Refresh) {
            // Refresh already requested - no point in setting anything else;
            return;
        }
        RESULT = result;
    }

    public static Result getAndReset() {
        Result result = RESULT;
        RESULT = null;
        return result;
    }
}
Run Code Online (Sandbox Code Playgroud)