I have a super class (Android's Fragment):
public abstract class BaseFragment<T> extends Fragment {
private T mListener;
public T getFragmentInteractionListener(){
return mListener;
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
castFragmentInteractionListener();
}
void castFragmentInteractionListener(){
Type superClassType = this.getClass().getGenericSuperclass();
if (superClassType instanceof ParameterizedType) {
try {
// I want to know if there is any way to check if the type argument has
// been set? So I can avoid the exception.
Class<T> listenerClazz = (Class<T>) ((ParameterizedType) superClassType).getActualTypeArguments()[0];
mListener = FragmentUtils.castFragmentInteractionListener(context, this, listenerClazz);
} catch (Exception e) {
}
}
}
}
and some sub classes derived from it.
public class FragmentDoesNotNeedListener extends BaseFragment {
}
public class FragmentHasListener extends BaseFragment<FragmentInteractionListener> {
interface FragmentInteractionListener {
void onClick();
void onExit();
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getFragmentInteractionListener().onClick();
}
}
Essentially, I want each fragment to derive from the BaseFragment
, most of them have the listener that can be called from themselves. I don't want to repeat the code to cast it, therefore create the base fragment and use generic type. However, some of the fragments do not need to use listener. But I don't how to check if the argument type is given or not.
In BaseFragment class, the method castFragmentInteractionListener
casts the class to a class field, and then uses it to cast the class into the listener. It is OK if the child class ( FragmentDoesNotNeedListener
) does not pass the generic type argument because the exception will be caught. However, I wonder if there is any way to check instead of catching the exception? Or maybe this is not a good design...
According to this StackOverflow post
Generic informations are erased at runtime , it cannot be recovered. A workaround is to pass the class T in parameter of a static method :
public class MyGenericClass {
private final Class<T> clazz; public static <U> MyGenericClass<U> createMyGeneric(Class<U> clazz) { return new MyGenericClass<U>(clazz); } protected MyGenericClass(Class<T> clazz) { this.clazz = clazz; } public void doSomething() { T instance = clazz.newInstance(); } }
It's ugly, but it works.
Or you could simply perform checks on which class you are in fact using
public abstract class BaseFragment<T> extends Fragment {
//...
public static Class classType(Class cls)
{
if(cls.equals(FragmentDoesNotNeedListener.class))
return FragmentDoesNotNeedListener.class;
else
if (cls.equals(FragmentHasListener.class))
return FragmentHasListener.class;
//else
// if(....)
else
return null;
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.