2017-11-14 24 views
11

Tôi có BaseFragment:loại Generic và đa hình

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

và nhiều lớp mà kéo dài nó. Ví dụ: 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); 
     } 
} 

Tôi muốn tránh lặp lại mã đồng bộ hóa vòng đời của từng đoạn và trình bày. Vì vậy, tôi muốn thực hiện quá trình này trong BaseFragment. Trong Java dòng này presenter.onAttachView(this); hoạt động nhưng với cảnh báo "Cuộc gọi không được kiểm tra onAttachView(V)" (Tôi có thể sống với điều này). Nhưng Kotlin không cho phép tôi làm điều này ở tất cả các

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

//... 
} 

Tôi thực sự cần lời khuyên về cách để làm điều này một cách chính xác.

được sửa đổi:

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

     } 
} 

Dưới đây là toàn bộ mã kiểm tra https://github.com/AlexNikolaTest/Test/tree/master/app/src/main/java/com/example/mytest

+0

Bạn có thể hiển thị phương thức 'onAttachView' từ người trình bày không? – OsipXD

Trả lời

3

lẽ bạn có thể làm cho nó như thế này

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

Tôi muốn đính kèm xem trong trình bày cơ sở –

+0

xin lỗi @AlexNik, tôi nghĩ rằng tôi bỏ qua một số điểm trong câu hỏi của bạn. vì vậy tôi chỉ chỉnh sửa câu trả lời của tôi. tôi đã loại bỏ một số phần, chỉ bao gồm 'attatchView' và' detachView' vì tôi nghĩ rằng 2 phương pháp mà bạn quan tâm nhất. –

+0

Hi @AlexNik chỉ tò mò, câu trả lời cập nhật của tôi có giúp bạn không? : D –

3

Bạn có thể thử này, sau đó bạn có thể có cảnh báo không được chọn trong Kotlin ;-)

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

Trong MainFragment bạn

syncLifeCycle(presenter as BasePresenter<BaseMvpView>) 

Không chắc chắn nếu nó hoạt động, chỉ cần chơi xung quanh một chút trong IntelliJ. Nhưng kể từ khi generics được xóa trong quá trình biên dịch và đúc một MainPresenter để BasePresenter cũng nên được tốt, có một cơ hội tốt nó đi qua.

5

Tôi nghĩ thay thế star-projection với BaseMvpView sẽ giúp

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

//... 
} 

Lý do là Kotlin phân biệt giữa outin tham số kiểu (còn gọi là hiệp biếnloại tham số contravariant, tương ứng).

in tham số kiểu nói rằng tham số kiểu là phải tiêu thụ bởi lớp generic, tức là sẽ được sử dụng như một tham số của một hàm, trong khi out tham số kiểu nêu rằng lớp generic sẽ sản xuất giá trị đã nhập thông số loại , tức là được sử dụng làm kiểu trả về cho một số hàm.

các onAttachView(V mvpView) mất một tham số kiểu contravariant mà ngụ ý rằng nó không được phép cho V là của bất kỳ loại (nó phải là kiểu BaseMvpView hoặc một lớp con) kể từ khi bạn là tốn giá trị đó. Tức là, nếu V hoàn toàn không xác định, chúng tôi không thể đọc thông số một cách an toàn vì V được mong đợi là một phiên bản BaseMvpView.Tuy nhiên, nếu trường hợp đó là onAttachViewsản xuất, tức là. trở về, V đối tượng thì phép chiếu sao sẽ hoạt động.

Hy vọng điều này sẽ hữu ích!

+0

Trong trường hợp đó tôi không thể gọi phương thức syncLifeCycle (người trình bày) từ MainFragment (loại generic MainMvpView không thể truyền sang BaseMvpView) –