如何解决在多个片段中使用 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 实例都相当昂贵,而且您很少需要在单个进程中访问多个实例。
您可以通过多种方式在多个活动和片段之间共享单个对象,例如:
- 使用 Dagger 并配置一个
@Singleton
,您可以在所有相关的 Activity 和 Fragment 中@Inject
。如果您是第一次设置 Dagger,则设置起来有些复杂,但这是专业应用程序中的常见选择。 - 使用经典的 Java 单例设计模式并将
RoomDB
转换为单例。 - 使用自定义
Application
子类,将RoomDB
实例放在那里并将其公开给任何Context
,例如((YourCustomApplication)context.getApplication()).getRoomDB()
我认为您最好的选择是 1) 可扩展性或 2) 简单性。
,我并不是说 Android Room 的使用是或应该是复杂的,但绝对没有你想象的那么简单;看着你的例子。 Android 开发人员花费大量时间尝试学习如何使用 Android Architecture Components 和 Dagger 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 举报,一经查实,本站将立刻删除。