【问题标题】:Kotlin - Best way to convert Singleton DatabaseController in AndroidKotlin - 在 Android 中转换 Singleton DatabaseController 的最佳方式
【发布时间】:2016-02-25 17:58:48
【问题描述】:

我正在从“Kotlin in Action”中学习 Kotlin,并且正在慢慢地将 Android 应用代码转换为它。但是我在转换下面的类时发现了一些问题。

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

我提出了两种不同的 Kotlin 实现,但它们都不能完全说服我。哪一个可以被认为是更好的解决方案?还是存在第三个更好的?

使用对象的第一个实现

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

第二个实现,所有内容都在一个文件中,我在每个需要数据库的活动的 onCreate() 中调用 initDatabase(..)

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

【问题讨论】:

  • 为什么不能只使用带有适当可见性修饰符的类?
  • @CaseyB 对不起,在什么意义上?
  • 很抱歉,我误读了您要执行的操作。你想让数据库控制器有一个返回自身实例的静态方法,对吧?
  • @CaseyB 是的,为了隐藏 SQLiteDatabase。主要问题是我没有找到 Kotlin 的任何官方翻译。
  • 我添加了一个应该做你想做的事情的答案。它几乎是您拥有的 Java 的直接端口。

标签: android kotlin


【解决方案1】:

我认为你想要的是一个伴生对象:

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!!
        }
    }
}

那么你可以这样称呼它:

val databaseController = DatabaseController.getInstance(context)

【讨论】:

  • 也可以在类声明中定义构造函数:class DatabaseController(val context: Context){...} 并定义一个init{...}块
  • 我对这个解决方案的唯一疑问是:伴生对象就像 java 中的静态字段一样工作,对吧?所以,它不会每次都实例化“实例”,对吗?
  • 它会在第一次调用 getInstance 时实例化实例。之后它将返回现有实例。
  • 非常感谢!! “Kotlin in Action” 欺骗了我,因为以单例对象为例,而伴随对象具有工厂方法,所以我不确定什么真正有效,什么无效。
猜你喜欢
  • 2018-03-08
  • 2013-06-23
  • 2017-04-21
  • 2019-10-24
  • 2017-09-19
  • 2015-11-21
  • 1970-01-01
  • 2021-01-18
  • 1970-01-01
相关资源
最近更新 更多