2017-11-14 20 views
11

私は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); 
    } 
} 

と多くのクラスを。たとえば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); 
     } 
} 

私は、各フラグメントおよびプレゼンターのライフサイクルの同期コードを繰り返さないようにしたいです。したがって、このプロセスはBaseFragmentに実装したいと考えています。 Javaでは、この行presenter.onAttachView(this);が動作しますが、警告「未チェックのコール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" 
    } 

//... 
} 

でこれを実行することはできません。

編集:ここでは

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

     } 
} 

は全体のテストコードは、https://github.com/AlexNikolaTest/Test/tree/master/app/src/main/java/com/example/mytest

+0

プレゼンターから 'onAttachView'メソッドを表示できますか? – OsipXD

答えて

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() { 
    } 
} 
+0

ベースプレゼンターのビューを添付したい –

+0

申し訳ありません@AlexNik、私はあなたの質問のいくつかの点をスキップすると思います。だから私はちょうど私の答えを編集しました。私はいくつかの部分を削除しました。あなたが最も関心を持っているこれらの2つの方法を考えているので、 'attatchView'と' detachView'だけを含んでいます。 –

+0

こんにちは@AlexNikだけ好奇心、私の更新された答えはあなたに役立つのですか? :D –

3

ようにそれを行うことができますあなたはこれを試すことができ、あなたが持つことができますKotlinでも未確認の警告が表示される;-)

あなたのMainFragment

syncLifeCycle(presenter as BasePresenter<BaseMvpView>) 

それが動作するかどうかわからない、では

if (presenter != null) { 
     val p = presenter as BasePresenter<BaseMvpView> 
     p.onAttachView(this) 
    } 
はただのIntelliJで少し周りを果たしました。しかし、コンパイル中にジェネリックが消去され、MainPresenterをBasePresenterにキャストすることもうまくいくはずなので、それが進む可能性があります。

5

私はBaseMvpViewstar-projectionを交換し

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

//... 
} 

理由はKotlinがoutin型パラメータ(それぞれ、共変反変パラメータ型として知られている)を区別することで役立つだろうと思います。

in型パラメータは、タイプパラメータがout型パラメータは、一般的なクラスは、値を生成することを述べるながらは、関数のパラメータとして使用すること、すなわち、ジェネリッククラスでを消費された状態型渡し型 パラメータ、つまり一部の関数の戻り値の型として使用されます。

onAttachView(V mvpView)Vは(それがタイプBaseMvpViewまたはサブクラスでなければならない)任意の型であるためにあなたがその値を消費しているので、それが許可されていないことを意味反変の型パラメータを取ります。つまり、Vが完全に不明の場合、VBaseMvpViewのインスタンスになると予想されるため、パラメータを安全に読み取ることができません。しかし、onAttachViewである場合には、を生成する。戻って、Vオブジェクト、そしてスタープロジェクションが機能します。

希望すると便利です。

+0

その場合、MainFragment(ジェネリック型MainMvpViewはBaseMvpViewにキャストできません)からメソッドsyncLifeCycle(プレゼンター)を呼び出すことができません。 –

関連する問題