微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在多个片段中使用 Room 数据库

如何解决在多个片段中使用 Room 数据库

我有 HomeActivity 活动,其中包含底部导航栏和 5 个片段。我想在所有这些片段中使用 RoomDatabase。我该如何实施?

家庭活动代码

public class HomeActivity extends AppCompatActivity {

    TextView tvDailyGoalValue;
    SharedPreferences sharedPreferences;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        //layout setting
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);
        BottomNavigationView navView = findViewById(R.id.nav_view);
        AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
                R.id.navigation_home,R.id.navigation_profile,R.id.navigation_notifications)
                .build();
        NavController navController = Navigation.findNavController(this,R.id.fragment3);
        NavigationUI.setupWithNavController(navView,navController);
       sharedPreferences = getSharedPreferences("MyPrefs",MODE_PRIVATE);
       RoomDB roomDB = Room.databaseBuilder(this,RoomDB.class,"dripdb").build();        
    }    
}

解决方法

您应该为 RoomDB 对象创建一个全局可访问的实例。 Room 文档甚至这样说:

如果您的应用在单个进程中运行,则在实例化 AppDatabase 对象时应遵循单例设计模式。每个 RoomDatabase 实例都相当昂贵,而且您很少需要在单个进程中访问多个实例。

您可以通过多种方式在多个活动和片段之间共享单个对象,例如:

  1. 使用 Dagger 并配置一个 @Singleton,您可以在所有相关的 Activity 和 Fragment 中@Inject。如果您是第一次设置 Dagger,则设置起来有些复杂,但这是专业应用程序中的常见选择。
  2. 使用经典的 Java 单例设计模式并将 RoomDB 转换为单例。
  3. 使用自定义 Application 子类,将 RoomDB 实例放在那里并将其公开给任何 Context,例如((YourCustomApplication)context.getApplication()).getRoomDB()

我认为您最好的选择是 1) 可扩展性或 2) 简单性。

,

我并不是说 Android Room 的使用是或应该是复杂的,但绝对没有你想象的那么简单;看着你的例子。 Android 开发人员花费大量时间尝试学习如何使用 Android Architecture ComponentsDagger 2 使他们的应用程序尽可能好,顺便说一下,这是 Google 推荐的用于 Android 的 API房间。不过,我还是要回答你的问题。

1.实体
决定您将在数据库中使用哪些实体。假设我们这里只有一个实体。类似的东西:

@Entity
class User constructor(
    @ColumnInfo(name = "first_name")
    var firstName: String,@ColumnInfo(name = "last_name")
    var lastName: String

    @PrimaryKey(autoGenerate = true)
    var id: Int = 0,)

2. DAO 类
像这样创建你的 DAO 类:

/**
 * Provides the abstraction API for accessing data.
 */
@Dao
interface AppDao {

    /**
     * Inserts a new [User].
     * @param user The user to insert.
     */
    @Insert
    suspend fun insertUser(user: User)

    /**
     * Updates the specified [User].
     * @param user The user to update.
     */
    @Update
    suspend fun updateUser(user: User)

    /**
     * Deletes the specified [User] from the database.
     * @param user The user to delete.
     */
    @Delete
    suspend fun deleteUser(user: User)
}

3.数据库类
在单独的类中创建数据库。 (例如。AppDatabase.java) 下面是一个好的数据库类的样子:

@Database(entities = [User::class],version = AppDatabase.VERSION)
abstract class AppDatabase : RoomDatabase() {

    /**
     * Returns the DAO for this application.
     * @return The DAO for this application.
     */
    abstract fun getAppDao(): AppDao

    companion object {

        private const val TAG = "AppDatabase"

        const val VERSION = 1
        private const val DATABASE_NAME = "inventory_database.db"

        @Volatile
        private var instance: AppDatabase? = null

        /**
         * Gets and returns the database instance if exists; otherwise,builds a new database.
         * @param context The context to access the application context.
         * @return The database instance.
         */
        fun getInstance(context: Context): AppDatabase =
            instance ?: synchronized(this) {
                instance ?: buildDatabase(context).also { instance = it }
            }

        /**
         * Creates and returns the callback object to execute when the database is first created.
         * @return The callback object to execute when the database is first created.
         */
        private fun appDatabaseCallback(): Callback = object : Callback() {

            override fun onCreate(db: SupportSQLiteDatabase) {
                super.onCreate(db)
                Log.d(TAG,"Database has been created.")

                // Throws exception
                CoroutineScope(Dispatchers.IO).launch {
                    instance?.getAppDao()?.let { populateDbAsync(it) }
                }
            }

            override fun onOpen(db: SupportSQLiteDatabase) {
                super.onOpen(db)
                Log.d(TAG,"Database has been opened.")
            }
        }

        /**
         * Builds and returns the database.
         * @param appContext The application context to reference.
         * @return The built database.
         */
        private fun buildDatabase(appContext: Context): AppDatabase {
            val filesDir = appContext.getExternalFilesDir(null)
            val dataDir = File(filesDir,"data")
            if (!dataDir.exists())
                dataDir.mkdir()

            val builder =
                Room.databaseBuilder(
                    appContext,AppDatabase::class.java,File(dataDir,DATABASE_NAME).toString()
                ).fallbackToDestructiveMigration()

            // Execute the callback only in DEBUG mode.
            if (BuildConfig.DEBUG) {
                builder.addCallback(appDatabaseCallback())
            }
            return builder.build()
        }

        /**
         * Populates the database when it is first created,as a suspended operation.
         * @param appDao The application DAO to execute queries.
         */
        private suspend fun populateDbAsync(appDao: AppDao) {

            withContext(Dispatchers.IO) {
                // Populate your database here...
            }

        }
    }
}

4.活动和片段

  • 活动
class MainActivity : AppCompatActivity() {

    private lateinit var dao: AppDao

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // Initialize the DAO..
        dao = AppDatabase.getInstance(requireContext()).getAppDao()
    }

    // An example of how to execute a dao method in an activity (Again,not recommended)
    private fun insertUser(firstName: String,lastName: String) {
        val user = User(firstName,lastName)
        
        lifecycleScope.launch { 
            dao.insertUser(user)
        }
    }

    // The rest of the code here...
}

您可以对所有活动执行相同的操作。

  • 片段
class ExampleFragment : Fragment(R.layout.fragment_example) {

    private lateinit var dao: AppDao

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

        // Initialize the DAO..
        dao = AppDatabase.getInstance(requireContext()).getAppDao()
    }

    // An example of how to execute a dao method in a fragment (Again,lastName)
        
        lifecycleScope.launch { 
            dao.insertUser(user)
        }
    }

    // The rest of the code here...
}

您可以对所有片段执行相同操作。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。