Java 如何检查Fragment.onAttach()中的类型化回调类型

Java 如何检查Fragment.onAttach()中的类型化回调类型,java,android,android-fragments,generics,inheritance,Java,Android,Android Fragments,Generics,Inheritance,我试图用类型化回调实现抽象片段,以便在几个子类中使用它 如何检查上下文是否为适当类的实例? 我的Abstract CallbackFragment代码: public abstract class CallbackFragment<C> extends Fragment { protected C mCallback; public CallbackFragment() { } @Override public void onAttach

我试图用类型化回调实现抽象片段,以便在几个子类中使用它

如何检查上下文是否为适当类的实例?

我的Abstract 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;
    }
}
公共抽象类CallbackFragment扩展了片段{
保护C-mCallback;
公共调用片段(){
}
@凌驾
公共void-onAttach(上下文){
super.onAttach(上下文);
//以防万一
if(上下文==null)
抛出新的NullPointerException();
试一试{
mCallback=(C)context;//此行似乎不会引发任何异常
}捕获(ClassCastException异常){
抛出新的RuntimeException(context.toString()+“必须实现回调”);
}
}
@凌驾
公共无效连接(){
super.onDetach();
mCallback=null;
}
}
车辆列表片段:

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() {
    }
}
public class BusListFragment
    extends VehicleListFragment<Bus> {

    //code specific for list of bus
    public BusListFragment() {
    }
}
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() {
    }
}
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() {
    }
}
公共抽象类VehicleListFragment
扩展CallbackFragment{
//回拨任何车辆的任何列表
公共接口回调{
void onListItemSelected(T selectedItem);
}
//任何车辆列表的通用代码
公共车辆登记册(){
}
}
公共汽车、卡车、船、自行车,无论是什么:

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() {
    }
}
public class BusListFragment
    extends VehicleListFragment<Bus> {

    //code specific for list of bus
    public BusListFragment() {
    }
}
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() {
    }
}
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() {
    }
}
公共类BusListFragment
扩展VehicleListFragment{
//总线列表的特定代码
公共BusListFragment(){
}
}
车辆详细信息片段:

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() {
    }
}
public class BusListFragment
    extends VehicleListFragment<Bus> {

    //code specific for list of bus
    public BusListFragment() {
    }
}
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() {
    }
}
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() {
    }
}
公共抽象类VehicleDetailsFragment
扩展CallbackFragment{
//任何车辆的常用回调方法
公共接口回调{
车辆上的无效编辑(T编辑项);
}
//任何车辆的通用代码
公共车辆细节碎片(){
}
}
公共汽车、卡车、船、自行车,无论细节如何:

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() {
    }
}
public class BusListFragment
    extends VehicleListFragment<Bus> {

    //code specific for list of bus
    public BusListFragment() {
    }
}
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() {
    }
}
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() {
    }
}
公共类总线详细信息片段
扩展VehicleDetailsFragment{
//特定于总线方法
公共接口回调
扩展VehicleDetailsFragment.Callback{
在某些特定情况下无效,或在某些特定情况下无效(公共汽车);
}
//总线专用代码
公共总线详细信息片段(){
}
}

我尝试为CallbackFragment添加一个抽象方法以获取回调类:

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");
        }
    }
}
公共抽象类CallbackFragment扩展了片段{
...
@非空
受保护的抽象类getCallbackClass();
@凌驾
公共void-onAttach(上下文){
super.onAttach(上下文);
...
//现在检查这样的实例
如果(!getCallbackClass().isAssignableFrom(context.getClass())){
抛出新的RuntimeException(context.toString()+“必须实现回调”);
}
}
}
使用BusDetails片段,一切看起来都正常:

public class BusDetailsFragment
        extends VehicleDetailsFragment<Bus, BusDetailsFragment.Callback> {

    @NonNull
    @Override
    protected Class<Callback> getCallbackClass() {
        return Callback.class;
    }

    ...
}
公共类总线详细信息片段
扩展VehicleDetailsFragment{
@非空
@凌驾
受保护的类getCallbackClass(){
返回Callback.class;
}
...
}
但不适用于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;
    }

    ...
}
公共类BusListFragment
扩展VehicleListFragment{
@非空
@凌驾
受保护的类getCallbackClass(){
/**
*我在这里看不到任何选择
*
*mCallback-仍然为null。因此,无法使用mCallback.getClass()
*
*Callback.class-无法从参数化类型中选择
*/
//返回mCallback.getClass();
//返回Callback.class;
}
...
}

当然,我可以为扩展VehicleListFragment.Callback的VehicleListFragment的每个子类创建一个自己的接口(就像在VehicleDetailsFragment的子类中一样),但它总是这样:

public interface Callback
        extends VehicleListFragment.Callback<Bus> {
    //nothing more here
}
公共接口回调
扩展VehicleListFragment.Callback{
//这里没有了
}
这看起来不是我的最佳选择可能还有其他解决方案吗?请分享您的想法。任何帮助都将不胜感激

mCallback = (C) context; //this line not seems to throw any exception
此调用永远不会引发异常。在运行期间,您的
C
被替换为
对象
(这称为类型擦除)-并且所有内容都是
对象
。因此,此时可以指定任何内容

若要在需要异常的位置获得异常(或至少错误确定),可以使用:

public abstract class CallbackFragment<C> extends Fragment {

    protected C mCallback;
    protected Class<C> callbackClass;

    public CallbackFragment(Class<C> clazz) {
       this.callbackClass = clazz;
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);

        //just in case
        if(context == null)
            throw new NullPointerException();

        if (clazz.isAssignableFrom(context.getClass()){
            mCallback = (C) context;  
        }else{
           //oops
        }
    }
}
公共抽象类CallbackFragment扩展了片段{
保护C-mCallback;
保护类回调类;
公共调用片段(类clazz){
this.callbackClass=clazz;
}
@凌驾
公共void-onAttach(上下文){
super.onAttach(上下文);
//以防万一
if(上下文==null)
抛出新的NullPointerException();
if(clazz.isAssignableFrom(context.getClass()){
mCallback=(C)上下文;
}否则{
//哎呀
}
}
}
然后你的碎片创造会从

 CallbackFragment<Something> fragment = new CallbackFragment<Something>();
CallbackFragment=newcallbackfragment();

CallbackFragment=newcallbackfragment(Something.class);
它有点不同,但允许您随时跟踪实际类型,绕过类型擦除

注:对于继承类,您可以更一般地执行此操作:

public abstract class CallbackFragment<C> extends Fragment {
    protected Class<C> callbackClass;

    public CallbackFragment() {
          this.callbackClass = (Class<C>) ((ParameterizedType) getClass()
                        .getGenericSuperclass()).getActualTypeArguments()[0];;
     }
}

public class CallbackFragmentOfSomething extends <CallbackFragment<Something>>{

}
公共抽象类CallbackFragment扩展了片段{
保护类回调类;
公共调用片段(){
this.callbackClass=(Class)((ParameterizedType)getClass()
.getGenericSuperclass()).getActualTypeArguments()[0];;
}
}
公共类CallbackFragmentOfSomething扩展{
}
如果您的实际类不是由于继承而定义的,而是“动态”定义的,则此操作将失败:

CallbackFragment=newcallbackfragment();
(所有内容都未经测试/没有复制粘贴,但应该有点准确)

这通电话永远不会给你带来麻烦