J'essaie d'implémenter un fragment abstrait avec un rappel typé pour l'utiliser dans plusieurs sous-classes.Comment vérifier le type de rappel typé dans Fragment.onAttach()
Comment puis-je vérifier si Context est l'instance de la classe appropriée?
Mon code de abstact CallbackFragment:
public abstract class CallbackFragment<C> extends Fragment {
protected C mCallback;
public CallbackFragment() {
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
//just in case
if(context == null)
throw new NullPointerException();
try {
mCallback = (C) context; //this line not seems to throw any exception
} catch (ClassCastException exception) {
throw new RuntimeException(context.toString() + " must implement Callbacks");
}
}
@Override
public void onDetach() {
super.onDetach();
mCallback = null;
}
}
fragment de la liste des véhicules:
public abstract class VehicleListFragment<T extends Vehicle>
extends CallbackFragment<VehicleListFragment.Callback<T>> {
//callback for any list of any vehicle
public interface Callback<T extends Vehicle> {
void onListItemSelected(T selectedItem);
}
//common code for list of any vehicle
public VehicleListFragment() {
}
}
Bus, camion, bateau, vélo, tout fragment liste:
public class BusListFragment
extends VehicleListFragment<Bus> {
//code specific for list of bus
public BusListFragment() {
}
}
Détails du véhicule fragment:
public abstract class VehicleDetailsFragment<T extends Vehicle, C extends VehicleDetailsFragment.Callback<T>>
extends CallbackFragment<C> {
//common methods of callback for any vehicle
public interface Callback<T> {
void onVehicleEdited(T editeItem);
}
//common code for any vehicle
public VehicleDetailsFragment() {
}
}
Bus, camion, bateau, vélo, tout détails fragment:
public class BusDetailsFragment
extends VehicleDetailsFragment<Bus, BusDetailsFragment.Callback> {
//specific for Bus methods
public interface Callback
extends VehicleDetailsFragment.Callback<Bus> {
void onSomethingSpecificForBusHappened(Bus bus);
}
//code specific for Bus
public BusDetailsFragment() {
}
}
J'ai essayé d'ajouter une méthode abstraite pour CallbackFragment pour obtenir la classe de rappel:
public abstract class CallbackFragment<C> extends Fragment {
...
@NonNull
protected abstract Class<C> getCallbackClass();
@Override
public void onAttach(Context context) {
super.onAttach(context);
...
//now checking instanceof like this
if(!getCallbackClass().isAssignableFrom(context.getClass())){
throw new RuntimeException(context.toString() + " must implement Callbacks");
}
}
}
Avec BusDetailsFragment tout semble OK:
public class BusDetailsFragment
extends VehicleDetailsFragment<Bus, BusDetailsFragment.Callback> {
@NonNull
@Override
protected Class<Callback> getCallbackClass() {
return Callback.class;
}
...
}
Mais pas avec BusListFragment:
public class BusListFragment
extends VehicleListFragment<Bus> {
@NonNull
@Override
protected Class<Callback<Bus>> getCallbackClass() {
/**
* I'm not seeing any option here
*
* mCallback - is null yet. So, there is no way to use mCallback.getClass()
*
* Callback<Bus>.class - Cannot select from parameterized type
*/
//return mCallback.getClass();
//return Callback<Bus>.class;
}
...
}
Bien sûr, je pourrais créer une propre interface pour chaque sous-classe de VehicleListFragment qui s'étend VehicleListFragment.Callback (comme dans les sous-classes de VehicleDetailsFragment) mais il regardera toujours comme ça :
public interface Callback
extends VehicleListFragment.Callback<Bus> {
//nothing more here
}
Cela ne semble pas être la meilleure option pour moi. Peut-être qu'il existe une autre solution? S'il vous plaît partagez vos pensées. Toute aide serait appréciée.
Mise à jour le 'admissible PS - était peu de mal :) – dognose
Wow! Merci. Je vais essayer ça. Je ne suis pas sûr que j'ai complètement compris votre réponse en ce moment. Avez-vous remarqué que Callback for BusListFragment est VehicleListFragment.Callback et que je ne peux pas obtenir .class de type paramétré? –
user2661298
@ user2661298 Il est assez difficile de garder une trace des génériques utilisant des génériques comme types ayant leurs propres types tout en héritant d'autres génériques avec d'autres types - sans être capable de déboguer étape par étape. Règle du pouce: Gardez une trace de votre classe réelle chaque fois que possible et vous pouvez déterminer les types de classe réels et "lancer la sauvegarde" à tout moment. – dognose