如何从资产预填充房间数据库?

2023-12-10

我正在使用 SQLiteOpenHelper 类编写一个应用程序,并决定使用 Room 重新构建它并实现 MVVM 模式,以获得一些额外的可用性。我的第一个问题是 Room 需要使用 .createFromAsset("database/data_table.db") 从资产文件夹加载数据库文件。它应该将其复制到设备,然后所有进程都从那里开始,但它不会根据需要复制它,开发人员网站除了如何调用它之外没有指定更多内容。这里是 数据库课程对每种方法进行了解释,以供学习之用,因为我正在学习过程中。

@Database(entities = MarkerObject.class, version = 1, exportSchema = false)
public abstract class MarkerDatabase extends RoomDatabase {

    /**We create the instance so we wouldn't create multiple instances
     of the database and use the same instance throughout the application
     which is accessed through the static variable **/
    private static MarkerDatabase instance;

    /**
     *This is used to access the Dao,
     * no body is provided because Room takes care of that,
     * abstract classes don't have methods but the room generates it because of the @Dao annotation.
     */
    public abstract MarkerDao markerDao();

    /**
     * This method creates a single instance of the database,
     * then we can call this method from the outside so we have a handle to it.
     * Synchronized means that only one thread at a time can access the database
     * eliminating creating multiple instances.
     */
    public static synchronized MarkerDatabase getInstance(Context context){

        /** we want to instantiate the database
         * only if we don't have an instance, thus the if condition */
        if (instance == null) {
            instance = Room.databaseBuilder(context.getApplicationContext(),
                    MarkerDatabase.class, "locations_table")
                    .createFromAsset("database/locations_table.db")
                    .build();
        }
        return instance;
    }
} 

The DAO

@Dao
public interface MarkerDao {

    @Query("SELECT * FROM locations_table")
    LiveData<List<MarkerObject>> getAllMarkers();

}

知识库

public class MarkerRepository {
  
    private MarkerDao markerDao;
    private LiveData<List<MarkerObject>> allMarkers;

    public MarkerRepository(Application application){
    
    MarkerDatabase markerDatabase = MarkerDatabase.getInstance(application);
    
    markerDao = markerDatabase.markerDao();
  
    allMarkers = markerDao.getAllMarkers();
}
public LiveData<List<MarkerObject>> getAllMarkers(){return allMarkers; }

}

视图模型

public class MarkerViewModel extends AndroidViewModel {
  
    private MarkerRepository repository;
    private LiveData<ArrayList<MarkerObject>> allMarkers;

    /**
     * We use the application as context in the constructor
     * because the ViewModel outlives the activities lifecycle.
     * To avoid memory leaks we use application as context instead of activities or views.
     */
    public MarkerViewModel(@NonNull Application application) {
        super(application);
        
        repository = new MarkerRepository(application);
        allMarkers = repository.getAllMarkers();
    }
    public LiveData<ArrayList<MarkerObject>> getAllMarkers(){
        return allMarkers;
    }
}

主要活动

public class MainActivity extends AppCompatActivity {
    private MarkerViewModel markerViewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView textView = findViewById(R.id.textView);

        markerViewModel = new ViewModelProvider(this).get(MarkerViewModel.class);
        markerViewModel.getAllMarkers().observe(this, new Observer<List<MarkerObject>>() {
            @Override
            public void onChanged(List<MarkerObject> markerObjects) {
                textView.setText(markerObjects.toString());
            }
        });
    }
}

现在我明白这对某些人来说可能是一个愚蠢的问题,我可能会因此而受到评判,但除了互联网之外我没有其他来源可以学习。非常感谢所有帮助。


您的代码很好,应该可以正常工作。

有几点需要检查:

  • First:确保location_table.db文件存在于app\src\main\assets\database目录

它应该将其复制到设备,然后所有进程都从那里开始,但它没有按要求复制它,开发者网站除了如何调用它之外没有指定更多内容

  • Second: createFromAsset() & createFromFile除非您对数据库执行某些事务或查询,否则永远不会执行并创建数据库文件。查看这里接受的答案了解更多信息。

UPDATE

错误是java.lang.RuntimeException: Cannot create an instance of class com.example.roomtextfirst.MarkerViewModeL

首先,我看不出您的新共享代码有任何问题。 我只需要您确保模块 gradle 文件中有以下依赖项:

implementation 'androidx.fragment:fragment:1.2.2'
implementation 'androidx.lifecycle:lifecycle-process:2.2.0'
implementation 'androidx.lifecycle:lifecycle-service:2.2.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-savedstate:2.2.0'
annotationProcessor 'androidx.lifecycle:lifecycle-compiler:2.2.0'

而不是已弃用的:

implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0-rc01'
annotationProcessor 'androidx.lifecycle:lifecycle-compiler:2.2.0-rc01'

也感谢您检查答案在这里这也可能会指导你。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何从资产预填充房间数据库? 的相关文章

随机推荐