2

I want to use data, that i am recieving from API response, in two different fragments.

Right now i have one activity and two fragments.

When app starts, there is API call in first fragment. Then i show results of API response. Also, i want to use the same result in second fragment. Data i want to use stored in List

So, my question is: do i have to make request in first fragment and somehow pass data to second fragment, or there is a way to make request outside fragment, strore result, and then use this result from both fragments?

Aleksey
  • 23
  • 3
  • You can make request in activity and then pass the response to both fragment in the bundle – AgentP Jul 14 '20 at 14:45
  • Easy way: make the request again. What you're asking: you can store the data in Shared preferences or use some kind of caching strategy when you're fetching data from the API. – ashu Jul 14 '20 at 14:47

3 Answers3

2

If You write Your application in MVVM architectural pattern I think You can use Shared ViewModel.
Android docs. Share data between fragments
Stack Overflow: Sharing data between fragments using ViewModel

It's very common that two or more fragments in an activity need to communicate with each other. Imagine a common case of master-detail fragments, where you have a fragment in which the user selects an item from a list and another fragment that displays the contents of the selected item.

public class SharedViewModel extends ViewModel {
    private final MutableLiveData<Item> selected = new MutableLiveData<Item>();

    public void select(Item item) {
        selected.setValue(item);
    }

    public LiveData<Item> getSelected() {
        return selected;
    }
}


public class MasterFragment extends Fragment {
    private SharedViewModel model;

    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        model = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
        itemSelector.setOnClickListener(item -> {
            model.select(item);
        });
    }
}

public class DetailFragment extends Fragment {

    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        SharedViewModel model = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
        model.getSelected().observe(getViewLifecycleOwner(), { item ->
           // Update the UI.
        });
    }
}
iknow
  • 8,358
  • 12
  • 41
  • 68
  • A link to a potential solution is always welcome, but please add context around the link so your fellow users will have some idea what it is and why it’s there. Always quote the most relevant part of an important link, in case the target site is unreachable or goes permanently offline. For more information check [this](https://meta.stackoverflow.com/tags/link-only-answers/info) – AgentP Jul 14 '20 at 14:58
  • Okay, I can add code but it is "hard" because the questioner didn't give any code and We don't even know If He/She writes code in Java or Kotlin. And websites I linked are official google android docs and stack overflow so I think it is not necessary to quote them. – iknow Jul 14 '20 at 15:46
  • 3
    That is a great answer, even if it's just links. MVVM refers to a specific architecture so there's not applicable code to accompany this link. Going with the MVVM architecture is also my suggestion since it's the cleaner approach – Eliza Camber Jul 14 '20 at 15:49
  • 1
    Thank you for you answer. Previously i wroted my app without any architecure pattern. I use JAVA. Now i am trying to refactor it using MVVM. I've created SharedViewModel. But when it came to solving my initial problem i stumbled on another question: how do i reuse data in different fragments if they didnt depent on each other? Link you provided says "It's very common that two or more fragments in an activity need to communicate with each other", but that's not my case. I want to use same data in different fragments without making new requests to API when switching between fragments. – Aleksey Jul 16 '20 at 14:43
  • 1
    But if You have the same ViewModel in both fragments You can use the same data on both fragments. So If on Fragment A you load data You load it to the variable in SharedViewModel class. Then You can use the same variable in Fragment B through SharedViewModel. So in code, I pasted to answer in `DetailFragment` instead of observing LiveData You can get value from `model.getSelected()` and use it. – iknow Jul 16 '20 at 14:58
  • 1
    Thank you very much! I've created repository with all the API calls. Then i've created SharedViewModel with one method `getForecast()` to retrieve data from repository. Now in both fragments i initialize model with `model = new ViewModelProvider(requireActivity()).get(SharedViewModel.class)` and after I observe changes with `model.getForecast().observe(getViewLifecycleOwner(), forecastData`. After this i operate with forecastData. Did I understand you correctly with my realisation of what you've suggested? – Aleksey Jul 17 '20 at 14:37
  • @Aleksey Yes, I think You have done everything correctly and it looks very similar to the official android [Guide to app architecture](https://developer.android.com/jetpack/guide). – iknow Jul 17 '20 at 14:46
0

May be i can explain it. You will have to create one class that extends FragmentStateAdapter , then you should create a single class that extends Fragment instead of having multiple classes and a layout.

Create ClassFragmentPagerAdapter like this:

public class ClassFragmentPagerAdapter extends FragmentStateAdapter {

public ClassFragmentPagerAdapter (@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle) {
    super(fragmentManager, lifecycle);
}

@NonNull
@Override
public Fragment createFragment(int position) {
    if (position == 0) {
        return new ClassFragment ();
    }
    return new ClassFragment ();
}


@Override
public int getItemCount() {
    return 2;
}

Then after that create the other ClassFragment that extends Fragment:

public class ClassFragment extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    super.onCreateView(inflater, container, savedInstanceState);

    View view = inflater.inflate(R.layout.layout_name, container, false);
    return view;

}

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    //do stuff here
}

Hope it helps! Happy coding:)

Bensal
  • 3,316
  • 1
  • 23
  • 35
0

There are a few ways to go about this.

The simplest solution to your problem is to use a Singleton. I strongly advise against this idea for many reasons, but most of the time it's the quickest way to get it up and running.

Another solution is to store the data in a member of the activity, and access that via (activity as MyActivity).myData.

garritfra
  • 546
  • 4
  • 21