Kotlin - Best way to convert Singleton DatabaseCon

2019-06-24 18:39发布

问题:

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()
        }
    }
}

回答1:

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)