Rafa
Rafa

Reputation: 3339

Kotlin parameter type mismatch

I'm trying to convert the following Java Code to Kotlin. It compiles and works fine.

public abstract class MvpViewHolder<P extends BasePresenter> extends RecyclerView.ViewHolder {
    protected P presenter;

    public MvpViewHolder(View itemView) {
        super(itemView);
    }

    public void bindPresenter(P presenter) {
        this.presenter = presenter;
        presenter.bindView(this);
    }

    public void unbindPresenter() {
        presenter = null;
    }
}

In the code I currently have, I get an error on the presenter.bindView(this) that states Required: Nothing, Found: MvpViewHolder.

abstract class MvpViewHolder<P>(itemView: View) : RecyclerView.ViewHolder(itemView) where P : BasePresenter<*,*> {
    protected var presenter: P? = null

    fun bindPresenter(presenter: P): Unit {
        this.presenter = presenter
        //I get the error here
        presenter.bindView(this)
    }

    fun unbindPresenter(): Unit {
        presenter = null
    }
}

bindView is defined like so

public abstract class BasePresenter<M,V> {
    fun bindView(view: V) {
        this.view = WeakReference(view)
    }
}

The only thing I can attribute it to right now is not defining the class generics correctly. As far as I can tell, this is still a correct instance of the View generic that is expected as the parameter, I also definitely don't see how it could be Nothing. How can I fix the bug?

EDIT: Java code for BasePresenter

public abstract class BasePresenter<M, V> {
    protected M model;
    private WeakReference<V> view;

    public void bindView(@NonNull V view) {
        this.view = new WeakReference<>(view);
        if (setupDone()) {
            updateView();
        }
    }

    protected V view() {
        if (view == null) {
            return null;
        } else {
            return view.get();
        }
    }
}

Upvotes: 1

Views: 5039

Answers (2)

Jo&#227;o Magalh&#227;es
Jo&#227;o Magalh&#227;es

Reputation: 2825

Your bindView method requires a View as an argument.

The error you're seeing appears when you define a variable (view defined on BasePresenter) that can hold a null result or, in your case, a View object.

On the code below you're binding this as the argument and MapViewHolder isn't a subclass of View.

abstract class MvpViewHolder<P>(itemView: View) : RecyclerView.ViewHolder(itemView) where P : BasePresenter<*,*> {
    protected var presenter: P? = null

    fun bindPresenter(presenter: P): Unit {
        this.presenter = presenter
        //I get the error here
        presenter.bindView(this) // -> this references MvpViewHolder which isn't a subclass of View
    }

    fun unbindPresenter(): Unit {
        presenter = null
    }
}

I think that what you want is to attach the itemView to the presenter because it is in fact a View object.

EDIT

The problem has to do with defining BasePresenter<*,*> which means in this case BasePresenter<Nothing, Nothing> (Nothing is an object in kotlin) - read more about star projections in kotlin on this link.

I would advice defining explicitly the types base presenter is expecting or defining explicitly as BasePresenter<Any?, Any?>.

Upvotes: 4

Sangeet Suresh
Sangeet Suresh

Reputation: 2545

You cannot directly use this to point to current class.

You need to use

this@class_name .

For example if "Example" is the class name, you can use

this@Example

It means this in Java

For more info visit https://kotlinlang.org/docs/reference/this-expressions.html

Upvotes: 0

Related Questions