Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin - Best way to convert Singleton DatabaseController in Android

Tags:

android

kotlin

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()
        }
    }
}
like image 759
gmariotti Avatar asked Feb 25 '16 17:02

gmariotti


People also ask

Which is the proper way to declare a singleton named Myclass in Kotlin?

In Kotlin, we need to use the object keyword to use Singleton class. The object class can have functions, properties, and the init method. The constructor method is not allowed in an object so we can use the init method if some initialization is required and the object can be defined inside a class.

How can you achieve Singleton pattern in Kotlin?

If we especially conversation around Android, we know that in Android we by and large have to pass a context instance to init block of a singleton. We can do it by using Early initialization and Apathetic initialization. In early initialization, all the components are initialized within the Application.

Is companion object singleton Kotlin?

In short, companion objects are singleton objects whose properties and functions are tied to a class but not to the instance of that class — basically like the “static” keyword in Java but with a twist.

How do I use singleton class in Kotlin?

Using Singletons in Kotlin. By using the keyword object in your app, you're defining a singleton. A singleton is a design pattern in which a given class has only one single instance inside the entire app.


1 Answers

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)
like image 82
CaseyB Avatar answered Sep 18 '22 19:09

CaseyB