Is there a method that works as the source fragment for the result?

I currently have a snippet in the overlay. This is to enter the service. In the phone app, each of the steps I want to show in the overlay is their own screens and actions. There are three parts to the login process, and each of them has its own activity, which was called using startActivityForResult ().

Now I want to do the same using fragments and overlay. The overlay will display a fragment corresponding to each activity. The problem is that these fragments are hosted in action in the Honeycomb API. I can make the first fragment work, but then I need to runActivityForResult (), which is impossible. Is there something at the start of startFragmentForResult () where I can start a new fragment, and when that happens, return the result to the previous fragment?

+70
android android-3.0-honeycomb android-fragments
Jul 19 2018-11-17T00:
source share
10 answers

All fragments live inside the Acts. Running a fragment for the result does not make much sense, because the activity in which it is located always has access to it, and vice versa. If a fragment is to convey the result, he can access his Activity and establish its result and complete it. In the case of replacing fragments in one action, the Activity activity is still available for both fragments, and all your messaging can simply go through the Activity.

Just remember that you always have a connection between a fragment and its activity. Starting and completing a result is a mechanism for communication between actions - The Activities can then delegate any necessary information to its fragments.

+45
Jul 19 '11 at 17:50
source share

If you want, there are some ways to communicate between fragments,

setTargetFragment(Fragment fragment, int requestCode) getTargetFragment() getTargetRequestCode() 

You can call back using these functions.

 Fragment invoker = getTargetFragment(); if(invoker != null) { invoker.callPublicMethod(); } 
+53
Nov 08 '11 at 13:16
source share

My 2 cents.

I switch between fragments, replacing the old fragment with a new one, using hide and show / add (existing / new). So, this answer is for developers who use fragments like me.

Then I use the onHiddenChanged method to find out that the old fragment has switched to the new one. See code below.

Before leaving a new fragment, I set the result in the global parameter, which will be requested by the old fragment. This is a very naive decision.

 @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; } } 
+4
May 12 '13 at 14:30
source share

In the snippet, you can call getActivity (). This will give you access to the activity that created the fragment. From there, you can call your customization method to set values ​​or pass values.

+1
Jul 22 '16 at 7:15
source share

There is an Android library - FlowR, which allows you to run snippets for results.

Running a snippet for the result.

 Flowr.open(RequestFragment.class) .displayFragmentForResults(getFragmentId(), REQUEST_CODE); 

Processing results in the calling fragment.

 @Override protected void onFragmentResults(int requestCode, int resultCode, Bundle data) { super.onFragmentResults(requestCode, resultCode, data); if (requestCode == REQUEST_CODE) { if (resultCode == Activity.RESULT_OK) { demoTextView.setText("Result OK"); } else { demoTextView.setText("Result CANCELED"); } } } 

Setting the result in a fragment.

 Flowr.closeWithResults(getResultsResponse(resultCode, resultData)); 
0
Jun 06 '18 at 5:24
source share

The easiest way to pass data back is setArgument (). For example, you have fragment1 that calls fragment2, which calls fragment3, fragment1 -> framgnet2 -> fargment3

In fragment 1

 public void navigateToFragment2() { if (fragmentManager == null) return; Fragment2 fragment = Fragment2.newInstance(); String tag = "Fragment 2 here"; fragmentManager.beginTransaction() .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE) .add(R.id.flContent, fragment, tag) .addToBackStack(null) .commitAllowingStateLoss(); } 

In fragment 2, we call fragment 3 ordinary

 private void navigateToFragment3() { if (fragmentManager == null) return; Fragment3 fragment = new Fragment3(); fragmentManager.beginTransaction() .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE) .replace(R.id.flContent, fragment, tag) .addToBackStack(null) .commit(); } 

When we finished the task in fragment 3, we now call the following:

 FragmentManager fragmentManager = getActivity().getSupportFragmentManager(); if (fragmentManager == null) return; fragmentManager.popBackStack(); Bundle bundle = new Bundle(); bundle.putString("bundle_filter", "data"); fragmentManager.findFragmentByTag("Fragment 2 here").setArguments(bundle); 

Now in fragment2 we can easily call arguments

 @Override public void onResume() { super.onResume(); Bundle rgs = getArguments(); if (args != null) String data = rgs.getString("bundle_filter"); } 
0
Aug 23 '18 at 11:12
source share

A solution using interfaces (and Kotlin). The main idea is to define a callback interface, inject it into your activity, and then call it from your fragment.

First create an ActionHandler interface:

 interface ActionHandler { fun handleAction(actionCode: String, result: Int) } 

Then call it from your child (in this case, your snippet):

 companion object { const val FRAGMENT_A_CLOSED = "com.example.fragment_a_closed" } fun closeFragment() { try { (activity as ActionHandler).handleAction(FRAGMENT_A_CLOSED, 1234) } catch (e: ClassCastException) { Timber.e("Calling activity can't get callback!") } dismiss() } 

Finally, implement this in your parent to get a callback (in this case, your activity):

 class MainActivity: ActionHandler { override fun handleAction(actionCode: String, result: Int) { when { actionCode == FragmentA.FRAGMENT_A_CLOSED -> { doSomething(result) } actionCode == FragmentB.FRAGMENT_B_CLOSED -> { doSomethingElse(result) } actionCode == FragmentC.FRAGMENT_C_CLOSED -> { doAnotherThing(result) } } } 
0
Oct 22 '18 at 21:21
source share

Another thing you can do depending on your architecture is to use a common ViewModel between fragments. Thus, in my case, FragmentA is the form, and FragmentB is the presentation of the element selection, where the user can search and select the element, saving it in the ViewModel. Then, when I return to FragmentA, the information is already saved!

0
Jan 6 '19 at 4:43
source share

We can just share the same representation model 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(this).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(this).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" } } 
0
Jan 29 '19 at 1:57
source share

You can use EventBus . This simplifies communication between actions, fragments, streams, services, etc. Less code, better quality.

-one
Aug 23 '18 at 6:43
source share



All Articles