![](/img/trans.png)
[英]Parsing JSON string array to Pojo/Entity for android sqlite database(Room)
[英]SQLite Room Fast Insert JSON Array
我正在创建一个词汇应用程序,它将单词/定义从JSON文件加载到JSON数组中。 然后,我遍历JSON数组以将数据加载到Room数据库中。
根据Log语句,JSON数组的加载速度非常快(大约最多1-2秒),但是Room数据库需要很长时间才能加载到异步线程中(大约40秒)。
我的MainActivity类尝试将单词从数据库加载到onCreate的布局中,但是很显然,由于数据库尚未完成加载,应用程序崩溃了。
建议的解决方法是什么? 仅供参考,该数据库仅需创建一次,并且仅在第一次加载后才能读取。
我对可能解决方案的想法:
1)第一次用户打开应用程序时使用JSONArray数据,然后在之后使用数据库
2)将数据文件的副本添加到资产文件夹,然后从那里访问(不确定如何与Room一起使用)
3)也许我的代码效率低下,并且有更快的方式加载Room DB?
private String fileName = "majortests_words.json";
private JSONArray wordBankAry;
Word currentWord = new Word();
int totalWords = 1000;
Random rand = new Random();
int currentWordIndex = 0;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
deleteDatabase("word-database");
loadWords();
DatabaseInitializer.populateAsync(AppDatabase.getAppDatabase(this), wordBankAry);
currentWordIndex = rand.nextInt(totalWords);
currentWord = AppDatabase.getAppDatabase(this).wordDao().getWord(currentWordIndex);
// code to add attributes of currentWord to the layout
public String loadJSONData() {
String jsonStr = null;
try {
InputStream iStream = getAssets().open(fileName);
int size = iStream.available();
byte[] buffer = new byte[size];
iStream.read(buffer);
iStream.close();
jsonStr = new String(buffer, "UTF-8");
} catch (IOException e) {
e.printStackTrace();
return null;
}
return jsonStr;
}
public void loadWords() {
try {
String jsonStr = loadJSONData();
JSONObject jsonObj = new JSONObject(jsonStr);
wordBankAry = jsonObj.getJSONArray("wordBank");
totalWords = wordBankAry.length();
Log.d("MainActivity", "JSON Count:" + wordBankAry.length());
} catch (JSONException e) {
e.printStackTrace();
}
}
。
@Database(entities = {Word.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
private static AppDatabase INSTANCE;
static String DB_NAME = "word-database";
public abstract WordDao wordDao();
public static AppDatabase getAppDatabase(Context context) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, DB_NAME).allowMainThreadQueries().build();
}
return INSTANCE;
}
public static void destroyInstance() {
INSTANCE = null;
}
}
。
@Dao
public interface WordDao {
@Insert
public void insertWords(Word word);
@Query("SELECT * FROM words")
List<Word> getAll();
@Query("SELECT * FROM words WHERE id = :id")
public Word getWord(int id);
}
。
public class DatabaseInitializer {
private static final String TAG = DatabaseInitializer.class.getName();
public static void populateAsync(@NonNull final AppDatabase db, JSONArray wordBankAry) {
PopulateDbAsync task = new PopulateDbAsync(db, wordBankAry);
task.execute();
}
public static Word addWord(final AppDatabase db, Word word) {
db.wordDao().insertWords(word);
return word;
}
private static void populateWordBank(AppDatabase db, JSONArray wordBankAry) {
Word word = new Word();
try {
for (int wordIndex = 0; wordIndex < wordBankAry.length(); wordIndex++) {
JSONObject jsonObj = wordBankAry.getJSONObject(wordIndex);
word.setWordName(jsonObj.getString("word"));
word.setWordDefinition(jsonObj.getString("definition"));
addWord(db, word);
}
} catch (JSONException e) {
e.printStackTrace();
}
List<Word> wordList = db.wordDao().getAll();
Log.d(DatabaseInitializer.TAG, "Rows Count:" + wordList.size());
}
private static class PopulateDbAsync extends AsyncTask<Void, Void, Void> {
private final AppDatabase mDb;
private JSONArray mWordBankAry;
PopulateDbAsync(AppDatabase db, JSONArray wordBankAry) {
mDb = db;
mWordBankAry = wordBankAry;
}
@Override
protected Void doInBackground(final Void... params) {
populateWordBank(mDb, mWordBankAry);
return null;
}
}
}
。
@Entity(tableName = "words")
public class Word {
@PrimaryKey(autoGenerate = true)
private int id;
@ColumnInfo(name = "word_name")
private String wordName;
@ColumnInfo(name = "word_definition")
private String wordDefinition;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getWordName() {
return wordName;
}
public void setWordName(String wordName) {
this.wordName = wordName;
}
public String getWordDefinition() {
return wordDefinition;
}
public void setWordDefinition(String wordDefinition) {
this.wordDefinition = wordDefinition;
}
}
建议的解决方法是什么?
将其替换为预打包的数据库。 SQLiteAssetHelper
可以与Room一起使用,尽管不如我所希望的那样干净。 有关此技术的演示,请参见此示例应用程序 。
也许我的代码效率低下,并且有更快的方式加载Room DB?
现在,您正在每个字执行一次数据库事务。 那会很慢。 而是使用@Insert
方法(将List<Word>
或Word[]
作为参数insert()
进行单个insert()
调用。 这应将所有这些插入自动包装到单个事务中。 一个大交易将比N个小交易更有效。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.