ObjectBox——objectBox数据库路径及自定义路径
目录
前言
之前已经讲了ObjectBox的基本配置,网上已经讲了很多ObjectBox的相关知识,但是ObjectBox的数据库存储路径问题,却极少提到,这节就让我们来探究下ObjectBox的数据存储路径吧。
今天涉及的知识有:
- ObjectBox数据库默认存储路径
- ObjectBox自定义存储路径
- ObjectBox数据库管理类封装
一.ObjectBox数据库默认存储路径
在使用Objectbox进行数据处理之前,我们先要初始化ObjectBox数据库,这时会涉及到BoxStore的初始化,让我们来看看初始化ObjectBox数据库代码吧:
private static BoxStore boxStore;
boxStore = MyObjectBox.builder()
.androidContext(context.getApplicationContext())
.build();
这段代码会在你项目的application中初始化。其中,让我们来看看
androidContext(context.getApplicationContext())
方法,追踪源码,会看到以下代码:
public BoxStoreBuilder androidContext(Object context) {
if (context == null) {
throw new NullPointerException("Context may not be null");
}
this.context = getApplicationContext(context);
File baseDir = getAndroidBaseDir(context);
if (!baseDir.exists()) {
baseDir.mkdir();
if (!baseDir.exists()) { // check baseDir.exists() because of potential concurrent processes
throw new RuntimeException("Could not init Android base dir at " + baseDir.getAbsolutePath());
}
}
if (!baseDir.isDirectory()) {
throw new RuntimeException("Android base dir is not a dir: " + baseDir.getAbsolutePath());
}
baseDirectory = baseDir;
android = true;
return this;
}
继续看其中涉及到的 getAndroidBaseDir(context) 方法:
static File getAndroidBaseDir(Object context) {
return new File(getAndroidFilesDir(context), "objectbox");
}
这里我们看到创建了一个File,getAndroidFilesDir(context)是一个路径,然后后面跟了一个"objectbox"值,"objectbox"是该路径下的一个文件夹名称,接着往下看
@Nonnull
private static File getAndroidFilesDir(Object context) {
File filesDir;
try {
Method getFilesDir = context.getClass().getMethod("getFilesDir");
filesDir = (File) getFilesDir.invoke(context);
if (filesDir == null) {
// Race condition in Android before 4.4: https://issuetracker.google.com/issues/36918154 ?
System.err.println("getFilesDir() returned null - retrying once...");
filesDir = (File) getFilesDir.invoke(context);
}
} catch (Exception e) {
throw new RuntimeException(
"Could not init with given Android context (must be sub class of android.content.Context)", e);
}
if (filesDir == null) {
throw new IllegalStateException("Android files dir is null");
}
if (!filesDir.exists()) {
throw new IllegalStateException("Android files dir does not exist");
}
return filesDir;
}
ok, getAndroidFilesDir(Object context) 方法其实是创建了一个文件夹路径。
接着我们看
boxStore = MyObjectBox.builder()
.androidContext(context.getApplicationContext())
.build();
中 的 “ .build()” 方法,追踪源码,显示如下:
/**
* Builds a {@link BoxStore} using any given configuration.
*/
public BoxStore build() {
if (directory == null) {
name = dbName(name);
directory = getDbDir(baseDirectory, name);
}
checkProvisionInitialDbFile();
return new BoxStore(this);
}
继续看 dbName(name) 方法:
private static String dbName(@Nullable String dbNameOrNull) {
return dbNameOrNull != null ? dbNameOrNull : DEFAULT_NAME;
}
这里出现了当 dbName(name)方法中的 name为null时,会设置一个默认name=DEFAULT_NAME,接着看追踪DEFAULT_NAME:
public static final String DEFAULT_NAME = "objectbox";
会发现以上 的都是在设置数据库的文件夹路径directory,所以由此看ObjectBox存储路径是 getAndroidFilesDir(Object context) / objectbox /objectbox/ ,接着我们看看ObjectBox数据库文件名及文件格式。接着看 “ .build()” 方法 中的:
checkProvisionInitialDbFile();
追踪看看:
private void checkProvisionInitialDbFile() {
if (initialDbFileFactory != null) {
String dataDir = BoxStore.getCanonicalPath(directory);
File file = new File(dataDir, "data.mdb");
if (!file.exists()) {
InputStream in = null;
OutputStream out = null;
try {
in = initialDbFileFactory.provide();
if (in == null) {
throw new DbException("Factory did not provide a resource");
}
in = new BufferedInputStream(in);
out = new BufferedOutputStream(new FileOutputStream(file));
IoUtils.copyAllBytes(in, out);
} catch (Exception e) {
throw new DbException("Could not provision initial data file", e);
} finally {
IoUtils.safeClose(out);
IoUtils.safeClose(in);
}
}
}
}
其中有一行:
File file = new File(dataDir, "data.mdb");
据此,我们知道ObjectBox的存储默认文件为:"data.mdb 。
ok,通过以上的追踪,得出ObjectBox默认存储路径为:
getAndroidFilesDir(Object context) / objectbox /objectbox/ data.mdb
getAndroidFilesDir(Object context) / objectbox /objectbox/ data.mdb
由于getAndroidFilesDir(Object context)是源码中一个私有方法。第一种方案,你可以将此方法拷贝出来,然后运行查看路径。第二种方案:我们大致可以看出此路径是在项目app的内部的,这里我直接运行自己的项目,然后查看手机app安装目录,在
/data/data/app包名/files/objectbox/objectbox/ 目录下看到以下截图
即,当 BoxStore 在初始化时,以:
public static void init(Context context) {
boxStore = MyObjectBox.builder()
.androidContext(context.getApplicationContext())
.build();
LogUtil.i("===BoxStore.version="+BoxStore.getVersion()+" BoxStore.versionNative="+BoxStore.getVersionNative());
}
方式创建的时候,ObjectBox数据库默认文件存储路径为:
/data/data/app包名/files/objectbox/objectbox/data.mdb
二.ObjectBox自定义存储路径
经过上面的研究,我们可以发现 boxStore对象是通过
boxStore = MyObjectBox.builder()
.androidContext(context.getApplicationContext())
.build();
获取到的,其实
boxStore = MyObjectBox.builder()
.androidContext(context.getApplicationContext())
.build();
而 androidContext(context.getApplicationContext()) 只不过是 boxStoreBuilder 的一个方法,boxStore 初始化本质是:
boxStore = boxStoreBuilder.build();
查看ObjectBox官网doc发现
BoxStoreBuilder 类的 directory(File directory) 方法可以设置数据库文件存储路径。
irectory(File directory) 中的 File 参数是一个文件夹路径。那么让我们先设置一个文件夹路径看看:
String filePath=context.getExternalFilesDir("objectbox").getAbsolutePath()+File.separator;
File file=new File(filePath);
BoxStoreBuilder boxStoreBuilder = MyObjectBox.builder()
.directory(setDBFilePath(context));//自定义数据库存储路径
mBoxStore = boxStoreBuilder.build();
查看设备中ObjectBox数据库文件路径:
Sdcard/Android/data/app包名/files/objectbox/
如下图:
注意:自定义数据库存储路径时,通过 directory(File directory) 方法只能设置一个文件夹路径,不能设置具体文件路径。而路径虽然自定义了,但文件名依然会默认是"data.mdb"。
废话不多说了,正片来了
三.ObjectBox数据库管理类封装
为了方便使用,我将ObjectBox封装成一个单例对象ObjectBoxManager。在Application中初始化ObjectBox数据库框架:
public class AppContext extends ComContext {
@Override
public void onCreate() {
super.onCreate();
//初始化ObjectBox
ObjectBoxManager.getInstance().init(this);
}
在MainActivity中处理数据类似下面这样(其中User为数据实体类):
Box userBox = ObjectBoxManager.getInstance().getBox(User.class);
//添加数据
User user=new User();
user.setAge(15);
user.setName("小明");
long id=userBox.put(user);
LogUtil.i("===存储id==="+id);
LogUtil.i("Inserted new note, ID: " + user.getId());
下面贴出ObjectBoxManager代码:
import android.content.Context;
import android.util.Log;
import java.io.File;
import io.objectbox.Box;
import io.objectbox.BoxStore;
import io.objectbox.BoxStoreBuilder;
import io.objectbox.android.AndroidObjectBrowser;
/**
* Title:ObjectBox数据库管理单例对象
*/
public class ObjectBoxManager {
private static final String TAG = "ObjectBoxManager";
//浏览器地址:http://localhost:8090/index.html
//adb指令:adb forward tcp:8090 tcp:8090
//设备/浏览器 设置数据库数据调试(只在调试模式时设置为true)
private static boolean isObjectBoxDebug=true;
private BoxStore mBoxStore;
private ObjectBoxManager(){}
private static class Holder {
private static ObjectBoxManager instance = new ObjectBoxManager();
}
public static ObjectBoxManager getInstance() {
return Holder.instance;
}
/**
* 在 Application 中初始化
* @param context 上下文
* @param isDefaultPath 是否启用默认路径
* @param dataBaseDirPath 数据库文件保存路径
*/
public void init(Context context,boolean isDefaultPath,String dataBaseDirPath) {
//自定义objectBox数据库文件路径
// /storage/emulated/0/Android/data/com.example.testdemo/files/objectbox/data.mdb
//自定义时只能定义文件夹路径,具体文件名仍然默认是 “data.mdb”
BoxStoreBuilder boxStoreBuilder;
if (isDefaultPath){
boxStoreBuilder=MyObjectBox.builder()
.androidContext(context.getApplicationContext());
}else{
boxStoreBuilder = MyObjectBox.builder()
.directory(setDBFilePath(dataBaseDirPath))//自定义数据库存储路径
.androidContext(context);
}
//获取BoxStore对象
mBoxStore = boxStoreBuilder.build();
Log.i(TAG,"===BoxStore.version="+BoxStore.getVersion()+" BoxStore.versionNative="+BoxStore.getVersionNative());
if(isObjectBoxDebug){
//可以理解为初始化连接浏览器(可以在浏览器中查看数据)
boolean start= new AndroidObjectBrowser(mBoxStore).start(context.getApplicationContext());
Log.i(TAG,"=====boxStore===start="+start);
}
}
/**自定义数据库存储路径**/
private File setDBFilePath(String dataBaseDirPath){
//自定义objectBox数据库文件路径
// /storage/emulated/0/Android/data/com.example.testdemo/files/objectbox/data.mdb
//自定义时只能定义文件夹路径,具体文件名仍然默认是 “data.mdb”
//String filePath=context.getExternalFilesDir("objectbox").getAbsolutePath()+File.separator;
return new File(dataBaseDirPath);
}
/***
* 获取Box对象
* @param cls 实体类对象,如:User.class
* @return 返回box操作对象
*/
public Box<?> getBox(Class<?>cls){
return mBoxStore.boxFor(cls);
}
/**获取BoxStore对象**/
public BoxStore getBoxStore(){
return mBoxStore;
}
/**
* 删除整个数据库文件(慎用)
* @return 返回boolean,为true表示删除数据库文件成功
*/
public boolean deleteDataBase() {
boolean isDelete = false;
if (mBoxStore != null) {
//关闭数据库
mBoxStore.close();
//删除数据库文件
isDelete = mBoxStore.deleteAllFiles();
Log.i(TAG,"=======delete database AllFiles=====" + isDelete);
}
return isDelete;
}
}
注意 : 封装类 ObjectBoxManager 中的 deleteDataBase 方法是删除整个数据库文件,一定要慎用。
ok,关于ObjectBox数据库文件存储路径相关知识就讲到这里了,谢谢大家