Skip to content

Instantly share code, notes, and snippets.

@keyboardr
Created December 8, 2016 01:54
Show Gist options
  • Select an option

  • Save keyboardr/5508c58ce6a02a7a8a0e9004efa9a0a7 to your computer and use it in GitHub Desktop.

Select an option

Save keyboardr/5508c58ce6a02a7a8a0e9004efa9a0a7 to your computer and use it in GitHub Desktop.

Revisions

  1. keyboardr created this gist Dec 8, 2016.
    30 changes: 30 additions & 0 deletions HeadlessFragmentFactory.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,30 @@
    /**
    * What you'd think an abstract factory would look like. Unfortunately, this class won't compile.
    */
    public abstract class HeadlessFragmentFactory<F extends Fragment & ParentedFragment<F, ? extends P>, P> {

    protected abstract F newInstance();

    /* There will be a compiler warning on P. When joining types, only the first type is allowed to
    be a class. All others MUST be interfaces. In this situation, there is no way for the compiler
    to know that P will be an interface. If P is removed, there is no longer a compile-time check
    that the parent implements the necessary callback interface */
    public <A extends FragmentActivity & P> F attach(A parent, String tag) {
    return attach(parent.getSupportFragmentManager(), tag);
    }

    // Same as above
    public <A extends Fragment & P> F attach(A parent, String tag) {
    return attach(parent.getChildFragmentManager(), tag);
    }

    private F attach(FragmentManager fragmentManager, String tag) {
    F frag = ((F) fragmentManager.findFragmentByTag(tag));
    if (frag == null) {
    frag = newInstance();
    fragmentManager.beginTransaction().add(frag, tag).commitNow();
    }
    return frag;
    }

    }
    23 changes: 23 additions & 0 deletions ParentedFragment.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,23 @@
    /**
    * Fragment that requires a parent of type P. T is a self-referential generic that also forces
    * the implementation to extend Fragment
    */
    public interface ParentedFragment<T extends Fragment & ParentedFragment<T, P>, P> {

    //Example parent interface
    interface FragmentParent {}

    //Example fragment implementation
    class ParentedFragmentImpl extends Fragment
    implements ParentedFragment<ParentedFragmentImpl, FragmentParent> {
    }

    //Example factory
    HeadlessFragmentFactory<ParentedFragmentImpl, FragmentParent> IMPL_FACTORY
    = new HeadlessFragmentFactory<ParentedFragmentImpl, FragmentParent>() {
    @Override
    protected ParentedFragmentImpl newInstance() {
    return new ParentedFragmentImpl();
    }
    };
    }