2016-10-10 4 views
2

У меня есть супер класс (фрагмент Андроида):Есть ли способ проверить, прошел ли подкласс для общего аргумента типа?

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) { 

      } 
     } 

    } 
} 

и некоторые вспомогательные классы, производные от него.

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(); 

    } 

} 

По существу, я хочу, чтобы каждый фрагмент, чтобы извлечь из BaseFragment, большинство из них имеют слушателя, который может быть вызван из себя. Я не хочу повторять код для его создания, поэтому создайте базовый фрагмент и используйте общий тип. Однако некоторым фрагментам не нужно использовать прослушиватель. Но я не могу проверить, указан ли тип аргумента или нет.

В классе BaseFragment метод castFragmentInteractionListener передает класс в поле класса, а затем использует его для приведения класса в слушатель. Это нормально, если дочерний класс (FragmentDoesNotNeedListener) не передает аргумент generic type, потому что исключение будет поймано. Однако, интересно, есть ли способ проверить вместо того, чтобы ловить исключение? Или, может быть, это не хороший дизайн ...

+0

зачем вам это нужно? Вы не можете использовать шаблон в Child? – Blackbelt

ответ

0

Согласно сообщению this StackOverflow

Общие сведения являются стерты во время выполнения, он не может быть восстановлен. Обойти это передать класс T в параметре статического метода:

общественного класса 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(); 
} } 

Это некрасиво, но это работает.

Или вы можете просто выполнить проверку того, какой класс вы на самом деле с помощью

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; 
     } 
} 
+0

Это нехорошее решение в моем случае. Потому что у меня есть 30 ~ 40 субфрагментов .... Однако я использовал для создания аннотации, в которой использовался класс как параметр. ех. @ListenerClass (clazz = Fragment1Listener.class). Но это не решение, которое мне нравится, потому что я не хочу дважды добавлять Fragment1Listener: один как аргумент аннотации, а другой - как аргумент общего типа. – Arst