Last active
February 18, 2022 20:10
-
-
Save zeroarst/3b3f32092d58698a4568cdb0919c9a93 to your computer and use it in GitHub Desktop.
Using annotation to autmatically cast Android fragment callback. This automatically handles attach&detach fragment listeners for reducing Boilerplate code.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public abstract class BaseCallbackFragment extends Fragment { | |
@Retention(RetentionPolicy.RUNTIME) | |
@Target(ElementType.TYPE) | |
public @interface FragmentCallback { | |
/** | |
* Determine if throws excpetion if target does not implement the callback. | |
* @return true: throws an exception if not implemented. | |
*/ | |
boolean mandatory() default true; | |
} | |
private List<Field> mFragmentCallbackFields = new ArrayList<>(); | |
@Override | |
public void onAttach(Activity activity) { | |
super.onAttach(activity); | |
castFragmentCallback(activity); | |
} | |
private void castFragmentCallback(Context context) { | |
for (Class<?> cls : this.getClass().getDeclaredClasses()) { | |
FragmentCallback callback = cls.getAnnotation(FragmentCallback.class); | |
if (callback == null) | |
continue; | |
for (Field f : this.getClass().getDeclaredFields()) { | |
if (f.getType() != cls) | |
continue; | |
String formatter = "%s must implement " + cls.toString(); | |
try { | |
if (getTargetFragment() != null) { | |
if (cls.isAssignableFrom(getTargetFragment().getClass())) { | |
if (!f.isAccessible()) | |
f.setAccessible(true); | |
f.set(this, getTargetFragment()); | |
mFragmentCallbackFields.add(f); | |
} else if (callback.mandatory()) | |
throw new ClassCastException(String.format(formatter, getTargetFragment().toString())); | |
} else if (getParentFragment() != null) { | |
if (cls.isAssignableFrom(getParentFragment().getClass())) { | |
if (!f.isAccessible()) | |
f.setAccessible(true); | |
f.set(this, getParentFragment()); | |
mFragmentCallbackFields.add(f); | |
} else if (callback.mandatory()) | |
throw new ClassCastException(String.format(formatter, getParentFragment().toString())); | |
} else { | |
if (cls.isAssignableFrom(context.getClass())) { | |
if (!f.isAccessible()) | |
f.setAccessible(true); | |
f.set(this, context); | |
mFragmentCallbackFields.add(f); | |
} else if (callback.mandatory()) | |
throw new ClassCastException(String.format(formatter, context.toString())); | |
} | |
} catch (IllegalAccessException e) { | |
Logger.e(TAG, e.getMessage(), e); | |
} | |
} | |
} | |
} | |
@Override | |
public void onDetach() { | |
super.onDetach(); | |
for (Field f : mFragmentCallbackFields) { | |
try { | |
f.set(this, null); | |
} catch (IllegalAccessException e) { | |
Log.e(TAG, e.getMessage(), e); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Example: