2016-02-26 62 views
1

我希望我的NewsListSubscriber繼承自使用泛型類型的RxJava訂閱服務器,但在調用UseCase execute方法時出現「類型不匹配」錯誤。我從Kotlin文檔中多次閱讀泛型頁面,但找不到解決方案。Kotlin:如何從RxJava訂閱服務器繼承

這是我用例:

abstract class UseCase(private val threadExecutor: IThreadExecutor, 
         private val postExecutionThread: IPostExecutionThread) { 

    private var subscription = Subscriptions.empty() 

    fun execute(UseCaseSubscriber: rx.Subscriber<Any>) { 
     subscription = buildUseCaseObservable() 
       .subscribeOn(Schedulers.from(threadExecutor)) 
       .observeOn(postExecutionThread.getScheduler()) 
       .subscribe(UseCaseSubscriber) 
    } 

    protected abstract fun buildUseCaseObservable(): Observable<out Any> 

    fun unsubscribe() { 
     if (!subscription.isUnsubscribed) { 
      subscription.unsubscribe() 
     } 
    } 
} 

這裏是我怎麼稱呼它:

override fun loadNewsList() { 
    getNewsListInteractor.execute(NewsListSubscriber()) 
} 

private inner class NewsListSubscriber : rx.Subscriber<List<NewsModel>>() { 
    override fun onCompleted() {// TODO} 

    override fun onError(e: Throwable) {// TODO} 

    override fun onNext(t: List<NewsModel>) {// TODO} 
} 

的錯誤是

「類型不匹配要求:rx.Subscriber。 Found:Presenters.NewsListPresenter.NewsListSubscriber「

在「execute(NewsListSubscriber())」行中。我試着玩「in」和「out」關鍵字,但我仍然有同樣的錯誤。

+0

是方法簽名中的Subscriber類與內部類中的rx.Subscriber超類相同嗎?只是檢查,在沒有看到進口的情況下無法確定。 –

+0

是的,我更新了我的代碼,在兩種情況下都使用rx.Subscriber。 – MickaelG

+0

'訂戶'等同於'Subscriber',它與任何更具體的符號不兼容。 解決方案是引入一個用於'execute()'輸入和'buildUsecase'輸出的泛型類型。 – Kiskae

回答

2

實際上有更好的方法來解決這個問題。我遇到了同樣的問題,並且每個派生訂戶類中的類型轉換都不是選項。

只需使用泛型類型參數更新抽象UseCase類即可。

abstract class UseCase<T>(private val threadExecutor: IThreadExecutor, 
        private val postExecutionThread: IPostExecutionThread) { 

    private var subscription = Subscriptions.empty() 

    fun execute(UseCaseSubscriber: rx.Subscriber<T>) { 
     subscription = buildUseCaseObservable() 
       .subscribeOn(Schedulers.from(threadExecutor)) 
       .observeOn(postExecutionThread.getScheduler()) 
       .subscribe(UseCaseSubscriber) 
    } 

    protected abstract fun buildUseCaseObservable(): Observable<T> 

    fun unsubscribe() { 
     if (!subscription.isUnsubscribed) { 
      subscription.unsubscribe() 
     } 
    } 
} 

當您聲明派生的UseCase類時,請在調用超類時使用泛型參數的具體類型。

class ConcreteUseCase(val threadExecutor: IThreadExecutor, 
       val postExecutionThread: IPostExecutionThread) 
       : UseCase<ConcreteType>(threadExecutor, postExecutionThread) 

這樣做,您可以在execute呼叫中使用輸入的訂閱者。

getNewsListInteractor.execute(NewsListSubscriber()) 

... 

private inner class NewsListSubscriber : rx.Subscriber<List<NewsModel() { 
    override fun onCompleted() {// TODO} 

    override fun onError(e: Throwable) {// TODO} 

    override fun onNext(t: List<NewsModel>) {// TODO} 
} 
0

我找到了解決辦法,實際上是非常簡單的:我NewsListSubscriber類必須從rx.Subscriber <任何>而不是rx.Subscriber <MyWantedClass>延伸。這意味着我需要將收到的對象轉換爲想要的類型。

private inner class NewsListSubscriber : DefaultSubscriber<Any>() { 

    override fun onCompleted() {} 

    override fun onError(e: Throwable) {} 

    override fun onNext(t: Any?) { 
     val newsList = t as List<News> 
     ... 
    } 
} 

在Java中,演員是在背景中完成的,但在Kotlin中我們需要自己做。

我還刪除了我的UseCase類中的所有「in」或「out」關鍵字。