泛型类型和多态性

Ale*_*Nik 11 generics android kotlin

我有BaseFragment:

    public abstract class BaseFragment extends Fragment implements BaseMvpView {

        private BasePresenter presenter;

        protected void syncLifeCycle(BasePresenter presenter) {
            this.presenter = presenter;
            this.presenter.onCreate();
        }

        @Override
        public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
            super.onViewCreated(view, savedInstanceState);

            //noinspection unchecked
            presenter.onAttachView(this); //it works with a warning
        }

        @Override
        public void onResume() {
            super.onResume();
            presenter.onResume();
        }

        @Override
        public void onPause() {
            super.onPause();
            presenter.onPause();
        }

        @Override
        public void onDestroyView() {
            super.onDestroyView();
            presenter.onDetachView();
        }

        @Override
        public void onDestroy() {
            super.onDestroy();
            presenter.onDestroy();
        }

        @Override
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            presenter.onActivityResult(requestCode, resultCode, data);
    }
}  
Run Code Online (Sandbox Code Playgroud)

以及许多扩展它的类.例如MainFragment:

    public class MainFragment extends BaseFragment implements MainMvpView {

        MainPresenter<MainMvpView> presenter;

        @Override
        public void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            syncLifeCycle(presenter);
            //presenter.onCreate();
        }

        @Override
        public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
            super.onViewCreated(view, savedInstanceState);
            //presenter.onAttachView(this);
        }

        @Override
        public void onResume() {
            super.onResume();
            //presenter.onResume();
        }

        @Override
        public void onPause() {
            super.onPause();
            //presenter.onPause();
        }

        @Override
        public void onDestroyView() {
            super.onDestroyView();
            //presenter.onDetachView();
        }

        @Override
        public void onDestroy() {
            super.onDestroy();
            //presenter.onDestroy();
        }

        @Override
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            //presenter.onActivityResult(requestCode, resultCode, data);
        }
}   
Run Code Online (Sandbox Code Playgroud)

我想避免重复每个片段和演示者的生命周期同步代码.因此我想在中实现这个过程BaseFragment.在Java中,这一行presenter.onAttachView(this);可以正常工作但有一个警告"Unchecked call onAttachView(V)"(我可以忍受这个).但是Kotlin根本不允许我这样做

abstract class BaseFragmentKotlin : Fragment(), BaseMvpView {

    private var presenter: BasePresenter<*>? = null

    //...

    override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        presenter?.onAttachView(this) //Does not work. "Out-projected type 'BasePresenter<*>?' prohibits the use of 'public abstract fun onAttachView(mvpView: V!): Unit defined in com.example.test.BasePresenter"
    }

//...
}
Run Code Online (Sandbox Code Playgroud)

我真的需要有关如何正确执行此操作的建议.

编辑:

    public class BasePresenterImpl<V extends BaseMvpView> implements BasePresenter<V> {

        @Nullable
        public V mvpView;

        @Override
        public void onCreate() {

        }

        @Override
        public void onAttachView(V mvpView) {
            this.mvpView = mvpView;
        }

        @Override
        public void onResume() {

        }

        @Override
        public void onPause() {

        }

        @Override
        public void onDetachView() {
        mvpView = null;
        }

        @Override
        public void onDestroy() {

        }

        @Override
        public void onActivityResult(int requestCode, int resultCode, Intent data) {

        }
}
Run Code Online (Sandbox Code Playgroud)

以下是整个测试代码https://github.com/AlexNikolaTest/Test/tree/master/app/src/main/java/com/example/mytest

Oma*_*abi 5

我想更换星级投影BaseMvpView将帮助

abstract class BaseFragmentKotlin : Fragment(), BaseMvpView {

    private var presenter: BasePresenter<BaseMvpView>? = null

    //...

    override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        presenter?.onAttachView(this)
    }

//...
}
Run Code Online (Sandbox Code Playgroud)

原因是Kotlin区分outin类型参数(也分别称为协变逆变参数类型).

in类型参数指出的类型参数是将要消耗由通用类,即,将用作的功能的参数,而out类型参数指出的一般类将产生传递型参数的值,即,将被用作一个某些功能的返回类型.

onAttachView(V mvpView)需要,这意味着它不允许用于逆变型参数V是任何类型(它必须是类型的BaseMvpView或子类),因为你正在消耗该值.也就是说,如果V完全未知,我们无法安全地读取参数,因为V预期是一个实例BaseMvpView.然而,如果onAttachView生产的情况,即返回,则V物体然后星形投影将起作用.

希望这可以帮助!


Kha*_*han 3

也许你可以这样做

interface IView

interface IPresenter {
    fun attachView(v: IView)
    fun detachView()
}

abstract class BasePresenter<V :IView> : IPresenter {
    protected var view: V? = null

    override fun attachView(v: IView) {
        this.view = v as V
    }

    override fun detachView() {
        view = null
    }
}

abstract class BaseFragment<P : IPresenter> : Fragment(), IView {
    protected lateinit var presenter: P

    override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        presenter.attachView(this)
    }

    override fun onDestroyView() {
        super.onDestroyView()
        presenter.detachView()
    }
}

interface TestView : IView {
    fun doSomething()
}

interface TestPresenter : IPresenter {
    fun doSomething()
}

class TestPresenterImpl : BasePresenter<TestView>(), TestPresenter {
    override fun doSomething() {
    }
}

class TestFragment : BaseFragment<TestPresenter>(), TestView {

    override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        presenter = TestPresenterImpl()
        presenter.doSomething()
    }

    override fun doSomething() {
    }
}
Run Code Online (Sandbox Code Playgroud)