Universal method for adding fragment, how to implement it

Viewed 110

I'm trying to create method for fragment's adding, that i will be able to use many times, but i've faced some error. This is my method:

// global variable
fragManager = getSupportFragmentManager();
private <T> void findFragmentByTagAndAdd(String fragmentTag, Class<?> cls, T t){
    Fragment fragm = fragManager.findFragmentByTag(fragmentTag);
    if (fragm == null) {
        fragm = cls.newInstance(t);
        fragManager.beginTransaction()
                .add(R.id.host_fragment_container, fragm)
                .commit();
    } 
}

Where T t is some data (for example some model class) that must be passed to setArguments of fragment's newInstance method

I get next error :

    cannot be applied to given types;
                    fragm = cls.newInstance(t);
                               ^   required: no arguments   
found: T#1   reason: actual and formal argument lists differ in length
4 Answers

Replace this:

fragm = cls.newInstance(t);

with something like:

Constructor constructor = cls.getConstructor(t.getClass());
fragm = (Fragment) constructor.newInstance(t);

Look at findFragmentByTagAndAdd method's Parameter Class cls, no use of this and it will be easy for you.

Do in this way:

Add interface like this.

interface IYourDesireClass<T>{
   T newInstance();
}

Implement this to your desired class.

class YourDesireClass implements IYourDesireClass<YourDesireClass>

And restructure method like this

private <T extends IYourDesireClass> void findFragmentByTagAndAdd(String fragmentTag, T t){
    Fragment fragm = fragManager.findFragmentByTag(fragmentTag);
    if (fragm == null) {
        fragm = t.newInstance();
        fragManager.beginTransaction()
                .add(R.id.host_fragment_container, fragm)
                .commit();
    } 
}

One more thing, try to avoid reflection. Reflection has a negative effect on performance.

Try this:

private void findFragmentByTagAndAdd(Fragment fragment, T t){
    FragmentManager fragmentManager = getSupportFragmentManager();
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    if(fragment != null){
        fragment.setArguments(t)
        fragmentTransaction.add(R.id.fragment_container, fragment);
        fragmentTransaction.commit();
      }
}

You can pass your data through setArguments()

Refer to this link as well: https://developer.android.com/guide/components/fragments

Thanks to Benoit's answer my method finally starts working and it looks like this:

    private <T> void findFragmentByTagAndAdd(String fragmentTag, Class<?> cls, T data){ 
    Fragment fragm = fragManager.findFragmentByTag(fragmentTag);
    if (fragm == null) {
        try{
            Constructor constructor = cls.getConstructor(data.getClass());
            fragm = (Fragment) constructor.newInstance(data);
        } catch (Exception e) {
        }
        fragManager.beginTransaction()
                .add(R.id.host_fragment_container, fragm, fragmentTag)
                .commit();
    }
}

And then i just call it:

findFragmentByTagAndAdd(DogsListFragment.DOGS_TAG, DogsListFragment.class, (Owner)owner);

Thanks all who was involved in my question, guys!

This method will be useful if you use multi-pane UI and have to add/replace fragments many times in your host-activity

Related