Search code examples
javaandroidkotlinandroid-loadermanager

Kotlin cannot identify parameters unless explicitly referenced


There is an issue that is befuddling me when trying to write an Android project in Kotlin.

When I try to call some basic Android library functions, the compiler is asking for very specific references. Here is an example where a LoaderManager is initialized. Take note of the last parameter.

  override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        loaderManager.initLoader(LOADER_ROUTINE, arguments, this as android.support.v4.app.LoaderManager.LoaderCallbacks<Cursor>)
   }

Here is the odd part. If I make a Java based Fragment, initialize the loader without the verbosity or compiler error and then convert to Kotlin, there is no error:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    loaderManager.initLoader(88, arguments, this)

}

What am I missing. What context does Kotlin need to prevent having to do the workaround of adding the as WhateverSpecificClass from the first example?

Edit: Here is some additional context. The specific error during compile is:

    Type inference failed: 

fun <D : Any!> initLoader
(id: Int,
 args: Bundle!,
 callback: LoaderManager.LoaderCallbacks<D!>!)
: Loader<D!>!
cannot be applied Int,
Bundle!,
EditRoutine
)

The entire wrapping code of the Fragment

    package com.inviscidlabs.ero.Fragments

import android.app.LoaderManager
import android.content.ContentValues
import android.content.Context
import android.content.CursorLoader
import android.content.Loader
import android.database.Cursor
import android.os.Bundle
import android.support.design.widget.TextInputEditText
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import butterknife.BindView
import butterknife.ButterKnife
import com.inviscidlabs.ero.Data.EroProvider
import com.inviscidlabs.ero.Data.Keys
import com.inviscidlabs.ero.Data.Routine
import com.inviscidlabs.ero.R



    class EditRoutine : Fragment(),  LoaderManager.LoaderCallbacks<Cursor>{

    //Values
    private val LOADER_ROUTINE: Int = 9150

    //Vars
    private var mRoutineID: String? = null

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)


        //If the routineID passed is a legitimate ID, initialize the loader
        if(!mRoutineID.equals(Keys.m_NullValue)){
            // this would not work: loaderManager.initLoader(LOADER_ROUTINE, arguments, this)
        loaderManager.initLoader(LOADER_ROUTINE, arguments, this as android.support.v4.app.LoaderManager.LoaderCallbacks<Cursor>)

        }
    }

    //Loader Functions


    override fun onCreateLoader(id: Int, args: Bundle): Loader<Cursor>? {
        if(id==LOADER_ROUTINE){

            val projection = arrayOf(Routine.Table._ID, Routine.Table.KEY_NAME)

            val selection = Routine.Table._ID + "=?"
            val selectionArgs = arrayOf(args.getString(Keys.b_RoutineID))

            val cL = CursorLoader(activity, //Context
                    EroProvider.CONTENT_URI_WORKOUT, //URI
                    projection, //The fields we want (must include ID
                    selection, //WHERE statement for SQL
                    selectionArgs, null)//Arguments for WHERE
            return cL
        }
        return  null
    }

    override fun onLoaderReset(loader: Loader<Cursor>?) {

    }

    override fun onLoadFinished(loader: Loader<Cursor>?, data: Cursor?) {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

}

Solution

  • The context parameter would be simply used from the LoaderCallbacks interface, so you would import its statement and implement it as part of the class signature as follows:

    import android.os.Bundle
    import android.support.v4.app.Fragment
    import android.support.v4.app.LoaderManager
    import android.support.v4.content.Loader
    import android.database.Cursor
    
    class WorkSpaceActivity : Fragment(), LoaderManager.LoaderCallbacks<Cursor> {
    
        override fun onActivityCreated(savedInstanceState: Bundle?) {
            super.onActivityCreated(savedInstanceState)
    
            loaderManager.initLoader(88, null, this)
        }
    
        override fun onCreateLoader(id: Int, args: Bundle?): Loader<Cursor> {
            TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
        }
    
        override fun onLoadFinished(loader: Loader<Cursor>?, data: Cursor?) {
            TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
        }
    
        override fun onLoaderReset(loader: Loader<Cursor>?) {
            TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
        }
    }