如何从资产预填充房间数据库? [英] How to pre-populate Room Database from asset?

查看:29
本文介绍了如何从资产预填充房间数据库?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I was writing an app with the SQLiteOpenHelper class and decided to re-build it all implementing the MVVM pattern using Room for some extra usability. My first issue is that the Room needs to load the database file from the assets folder using the .createFromAsset("database/data_table.db"). It should copy it to the device and then all processes go from there but it doesn't copy it as required, the developer website doesn't specify more than how to call it. Here is the Database class with explanation of each method for learning purposes, since I am in the learning process.

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

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

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

Now I understand that this might be a stupid question to some and I might be judged for it but I don't have other sources other than the internet to learn from. All help is very well appreciated.

推荐答案

你的代码很好,应该没有任何问题.

Your code is fine and should work without any problems.

需要检查的几件事:

  • 第一:确保location_table.db文件存在于app\src\main\assets\database目录下
  • First: make sure that location_table.db file exists under app\src\main\assets\database directory

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

It should copy it to the device and then all processes go from there but it doesn't copy it as required, the developer website doesn't specify more than how to call it

  • 第二:createFromAsset() &createFromFile 永远不会被执行并创建数据库文件,除非您对数据库进行一些事务或查询.查看此处接受的答案了解更多信息.
    • Second: createFromAsset() & createFromFile never get executed and create the database file unless you do some transaction or query to the database. Check the accepted answer here for more info.
    • 更新

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

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

      First I can't see any problems with your new shared code. I just need you to make sure that you have the below dependencies in module gradle file:

      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'
      

      还要感谢查看此处的答案,它们可能会指导您

      Also thanks to check the answers here that might guide you as well.

      这篇关于如何从资产预填充房间数据库?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆