2017-11-14 3 views
11

Ich habe BaseFragment:generische Typen und Polymorphismus

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

und viele Klassen, die sie erweitert. Zum Beispiel 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); 
     } 
} 

Ich möchte den Lebenszyklus Synchronisationscode jedes Fragments und Moderator zu wiederholen. Daher möchte ich diesen Prozess in der BaseFragment implementieren. In Java funktioniert diese Zeile presenter.onAttachView(this); aber mit einer Warnung "Ungeprüfter Anruf onAttachView(V)" (damit kann ich leben). Aber Kotlin erlaubt mir nicht, das überhaupt ich wirklich

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

//... 
} 

tun müssen, Ratschläge, wie man dies richtig zu tun.

Edited:

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

     } 
} 

Hier ist die gesamte Testcode https://github.com/AlexNikolaTest/Test/tree/master/app/src/main/java/com/example/mytest

+0

Können Sie 'onAttachView'-Methode vom Presenter zeigen? – OsipXD

Antwort

3

Vielleicht können Sie es wie folgt

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

Ich möchte Ansicht in Base Presenter –

+0

beifügen Sorry @AlexNik, ich denke, ich überspringe einige Punkte Ihrer Frage. Also habe ich gerade meine Antwort bearbeitet. Ich habe einige Teile entfernt, nur "attatchView" und "detachView", da ich denke, diese 2 Methoden, die Sie am meisten interessiert sind. –

+0

Hallo @AlexNik nur neugierig, ist meine aktualisierte Antwort Ihnen helfen? : D –

3

du versuchen machen könnte, dann können Sie das haben ungeprüfte Warnung auch in Kotlin ;-)

if (presenter != null) { 
     val p = presenter as BasePresenter<BaseMvpView> 
     p.onAttachView(this) 
    } 

In Ihrem MainFragment

syncLifeCycle(presenter as BasePresenter<BaseMvpView>) 

Nicht sicher, ob es funktioniert, nur um ein wenig in IntelliJ gespielt. Aber da Generika beim Kompilieren gelöscht werden und ein MainPresenter zu BasePresenter gegossen werden sollte, sollte es auch funktionieren.

5

glaube, ich würde die star-projection mit BaseMvpView ersetzt

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

//... 
} 

helfen Der Grund dafür ist, dass Kotlin zwischen out und in Typparametern unterscheidet (auch als covariant bekannt und kontra Parametertypen, respectively).

in Typparameter angeben, dass der Typ-Parameter verbraucht durch die generische Klasse, also verwendet werden als Parameter einer Funktion, während out Typparameter angeben, dass die generische Klasse erzeugen ein Wert zu sein, ist Übergabetyp Parameter, dh als Rückgabetyp für eine Funktion verwendet werden.

die onAttachView(V mvpView) nimmt einen kontra Typ Parameter, der bedeutet, dass es nicht für V jeglicher Art sein darf (es hat vom Typ BaseMvpView oder einer Unterklasse sein), da Sie raubend dieser Wert sind. Das heißt, wenn V völlig unbekannt war, können wir den Parameter nicht sicher lesen, da erwartet wird, dass V eine Instanz von BaseMvpView ist.Wenn es jedoch der Fall wäre, dass onAttachView produziert, d. H. Rückkehr, V Objekt, dann würde die Sternenprojektion funktionieren.

Hoffe, das hilft!

+0

In diesem Fall kann ich nicht Methode SyncLifeCycle (Presenter) von MainFragment aufrufen (generischer Typ MainMvpView kann nicht in BaseMvpView umgewandelt werden) –