5

I'm learning Kotlin from "Kotlin in Action" and I'm slowly converting an Android app code to it. But I have found some problem in converting the following class.

public class DatabaseController {
  private static DatabaseController sDatabaseController;

  private SQLiteDatabase mDatabase;

  private DatabaseController(Context context) {
    mDatabase = new SQLiteOpenHelperImpl(context.getApplicationContext())
            .getWritableDatabase();
  }

  public static DatabaseController getDatabaseController(Context context) {
    if (sDatabaseController == null) {
        sDatabaseController = new DatabaseController(context);
    }
    return sDatabaseController;
  }

  public void addElement(Element element) {
    if (element != null) {
        ContentValues values = getContentValues(element);

        mDatabase.beginTransaction();
        try {
            // insert element
            mDatabase.setTransactionSuccessful();
        } finally {
            mDatabase.endTransaction();
        }
    }
}

I've come up with two different Kotlin implementation, but neither of them fully convince me. Which one can be considered a better solution? Or does exist a third one that is better?

First implementation using object

object DatabaseControllerObject {
  private var mDatabase : SQLiteDatabase? = null

  fun initDatabase(context: Context) {
    mDatabase = mDatabase?: SQLiteOpenHelperImpl(context.applicationContext).writableDatabase
  }

  fun addElement(context: Context, element: Element) {
    initDatabase(context)
    // insert alarm
    mDatabase?.let {
    // CODE
    }
}

Second implementation with everything in a single file, where I call initDatabase(..) in the onCreate() of each activity that needs the database

private var mDatabase: SQLiteDatabase? = null

fun initDatabase(context: Context) {
    mDatabase = mDatabase ?: SQLiteOpenHelperImpl(context.applicationContext).writableDatabase
}

fun addElement(element: Element) {
    val values = getContentValues(element)

    mDatabase?.let {
        it.beginTransaction()
        try {
          // insert
          it.setTransactionSuccessful()
        } finally {
          it.endTransaction()
        }
    }
}
gmariotti
  • 479
  • 4
  • 14
  • Why can't you just use a class with whatever is the appropriate visibility modifier? – CaseyB Feb 25 '16 at 20:15
  • @CaseyB sorry, in which sense? – gmariotti Feb 25 '16 at 20:47
  • I'm sorry I misread what you're trying to do. You want to make Database controller have a static method that returns an instance of itself, right? – CaseyB Feb 25 '16 at 21:05
  • @CaseyB yes, in order to hide the SQLiteDatabase. The main problem is that with Kotlin I didn't find any official translation of it. – gmariotti Feb 25 '16 at 21:09
  • I added an answer that should do what you want. It's almost a direct port of the Java you have. – CaseyB Feb 25 '16 at 21:17

1 Answers1

5

I think what you want is a companion object:

class DatabaseController
{
    private constructor(context: Context)
    {
        // ...
    }

    companion object
    {
        private var instance: DatabaseController? = null
        fun getInstance(context: Context): DatabaseController
        {
            if(instance == null)
            {
                instance = DatabaseController(context)
            }

            return instance!!
        }
    }
}

Then you can just call it like this:

val databaseController = DatabaseController.getInstance(context)
CaseyB
  • 24,780
  • 14
  • 77
  • 112
  • You can also define the constructor in the class declaration : class DatabaseController(val context: Context){...} and define an init{...} block – LucasFM Feb 26 '16 at 08:47
  • My only doubt about this solution is: the companion object works like a static field in java right? So, it will not instantiate 'instance' everytime, am I correct? – gmariotti Feb 26 '16 at 09:17
  • It will instantiate instance the first time getInstance is called. After that it will return the existing instance. – CaseyB Feb 26 '16 at 13:16
  • 1
    Thank you so much!! "Kotlin in Action" tricked me because shows object with singleton as an example, while companion object with factory methods, so I wasn't sure of what really was working and what wasn't. – gmariotti Feb 26 '16 at 16:19