Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Launching Fragment B from Activity based on data collected from Fragment A with less boilerplate code

I have the following setup:

  1. I have an Activity that launches a FragmentA.
    FragmentA contains a recyclerView and an adapter.

  2. I have an interfaceA in the adapter which is implemented in FragmentA so that I get notified which position was clicked.

  3. I have a second interfaceB that I created in the FragmentA, which is implemented in the Activity that launched FragmentA in step 1.

  4. Finally, I'm launching FragmentB from the Activity based on data I get from interfaceB.

Everything is working fine, however the flow is tedious, and demands a lot of boilerplate code.

THE GOAL is to have the activity launch fragmentB that contains data from a single clicked item from the recyclerView within FragmentA.

Question: Can it be achieved differently?

Code Below:

Activity launches FragmentA:

Fragment fragment = fragmentManager.findFragmentByTag(FragmentA.class.getName());
    if (fragment == null) {

        fragment = Fragment.instantiate(this, FragmentA.class.getName());
    }
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    fragmentTransaction
            .replace(R.id.fragmentLayout, fragment, FragmentA.class.getName())
            .addToBackStack(FragmentA.class.getName())
            .commit();

Inside FragmentA we have recyclerView, and interfaceA implemented in the adapter:

Adapter Class:

        public class AdapterA extends RecyclerView.Adapter< AdapterA.ViewHolderA> {
        
        //instances
        private Context context;
        private List<Data> dataList;
        private OnItemClickListener onItemListClickListener;
        
        //Constructor
        public AdapterA (Context context, List<Data> dataList, OnItemClickListener onItemListClickListener {
        this.context = context;
        this.dataList = dataList;
        this.onItemListClickListener = onItemListClickListener;
    }

onCreateViewHolder....
onBindViewHolder....
getItemCount...

class ViewHolderA RecyclerView.ViewHolder {
//instances..
//Constructor...

}
        }

interface class interfaceA:

public interface OnItemClickListener {
    void onItemClick(View view, int position);
}

interface class interfaceB:

public interface SingleItemEventListener {
    void onSingleItemClicked(int position);
}

FragmentA class:

//Instances
private AdapterA adapter;
private RecyclerView recyclerView;
private onSingleItemClicked singleItemEventListener;

onAttach...
onCreateView...

@Override
public void onStart() {
    super.onStart();

    //Setting adapter
    onSetAdapter();
}

private void onSetAdapter() {
    List<Data> dataList;

    dataList = getData();

    adapter = new AdapterA(context, dataList, new OnItemClickListener() {
        @Override
        public void onItemClick(View view, int position) {
            singleItemEventListener.onSingleItemClicked(position);
        }
    });

In the Activity, we are implementing onSingleItemClicked callback to receive the event and launch FragmentB with data received from the interface callback:

ActivityA implements SingleItemEventListener {
@Override
    public void onSingleItemClicked(int position) {
Data data = getData(position);

if (data != null) {
Bundle bundle = new Bundle();
bundle.putParcelable("single_data_key", data);
Fragment fragmentB = fragmentManager.findFragmentByTag(FragmentB.class.getName());

        if (fragmentB == null && bundle != null) {
            fragmentB = Fragment.instantiate(this, FragmentB.class.getName(), bundle);
        }

        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction
                .replace(R.id.FragmentLayout, fragmentB, FragmentB.class.getName())
                .addToBackStack(FragmentB.class.getName())
                .commit();
}
}
}
like image 641
Red M Avatar asked Jul 12 '18 17:07

Red M


People also ask

How do I start an activity from kotlin fragment?

You can either add or replace fragment in your activity. Create a FrameLayout in activity layout xml file. Show activity on this post. Show activity on this post.

How do I start an intent from a fragment?

If you want to start a new instance of mFragmentFavorite , you can do so via an Intent . Intent intent = new Intent(this, mFragmentFavorite. class); startActivity(intent);


1 Answers

Add ViewModel to your activity and use it to communicate between all you components, activity and both fragments.

You can get access to the activity's ViewModel from your fragment

MyViewModel model = ViewModelProviders.of(getActivity()).get(MyViewModel.class);

Use LiveData for communication, post an action to it from your fragment and listen to it in your activity to start another fragment.

like image 96
TpoM6oH Avatar answered Oct 17 '22 01:10

TpoM6oH