使用 Retrofit2 插入 + 4500 个项目,每个项目有 7 列到 SQlite 数据库中
Inserting + 4500 items with 7 columns each into SQlite Database with Retrofit2
我正在为手持扫描设备开发 Android 应用程序,并希望通过 Retrofit2 从 MySQL 数据库下载大约 4.500 个项目到设备上的 SQlite 数据库中;因此,当我尝试一次下载所有项目时,它会减慢 UI 并冻结应用程序长达 5 分钟;我在谷歌上搜索了很多关于如何解决这个问题的方法,但现在还没有找到合适的解决方案;因此,我尝试通过在 For-each 循环中迭代并在后台威胁中使用 .stream() 和 .limit() ,像这样:
public static void writeItemsToDatabase(Context mContext, String basic) {
//creating the itemApi interface
ItemApi itemApi = retrofit.create(ItemApi.class);
//making the call object
Call<List<Item>> call = itemApi.checkItems(basic);
call.enqueue(new Callback<List<Item>>() {
@Override
public void onResponse(@NonNull Call<List<Item>> call,
@NonNull Response<List<Item>> response) {
if (response.isSuccess()) {
List<Item> itemList;
itemList = response.body();
int dataSize = response.body().size();
Log.d(TAGGG, String.valueOf(dataSize));
itemList.forEach(List -> Log.d(TAGGG, String.valueOf(List.getEan())));
itemList.forEach(List -> Log.d(TAGGG, String.valueOf(List.getNo())));
class DownloadTask extends AsyncTask<String, Integer, String> {
// Runs in UI before background thread is called
@Override
protected void onPreExecute() {
super.onPreExecute();
// Do something like display a progress bar
}
// This is run in a background thread
@Override
protected String doInBackground(String... params) {
// Do something that takes a long time, for example:
for (int i = 0; i <= 3 ; i++) {
try (DatabaseHandler itemsManager = new DatabaseHandler((XXXXApp)
mContext.getApplicationContext())) {
itemList.stream().limit(1500).forEach(item -> {
itemsManager.addItem(item);
itemsManager.close();
});
}
// Call this to update your progress
publishProgress(i);
}
return "this string is passed to onPostExecute";
}
// This is called from background thread but runs in UI
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
// Do things like update the progress bar
}
// This runs in UI when background thread finishes
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// Do things like hide the progress bar or change a TextView
}
}
new DownloadTask().execute();
}
}
@Override
public void onFailure(Call<List<Item>> call, Throwable t) {}
});
return;
}
但是,结果并不令人满意,因为数据库没有正确下载;我将 i 的值更改为 9 并将 .limit() 的值更改为 500(以实现相同的结果,即下载 +4.500 项),结果相同。
问题肯定出在这段代码中:
for (int i = 0; i <= 3 ; i++) {
try (DatabaseHandler itemsManager = new DatabaseHandler((XXXApp)
mContext.getApplicationContext()))
{
itemList.stream().limit(1500).forEach(item -> {
itemsManager.addItem(item);
itemsManager.close();
});
}
// Call this to update your progress
publishProgress(i);
}
这是我在大量谷歌搜索后找到的最接近我想要实现的方法;问题当然是每次关闭数据库并重新打开它的 For-Loop;我也不确定 SQlite 数据库的数据量是否太大;因此,非常感谢任何有关如何正确解决此问题的帮助或提示,谢谢!
- Create once instance of DatabaseHandler(what is it? you can use room with more comfortable API) and reuse it.
- Insert many(100-500) items in one transaction.
或者您可以在服务器端创建 sqlite 数据库文件,然后下载它并在 android 应用程序中作为数据库打开。
我正在为手持扫描设备开发 Android 应用程序,并希望通过 Retrofit2 从 MySQL 数据库下载大约 4.500 个项目到设备上的 SQlite 数据库中;因此,当我尝试一次下载所有项目时,它会减慢 UI 并冻结应用程序长达 5 分钟;我在谷歌上搜索了很多关于如何解决这个问题的方法,但现在还没有找到合适的解决方案;因此,我尝试通过在 For-each 循环中迭代并在后台威胁中使用 .stream() 和 .limit() ,像这样:
public static void writeItemsToDatabase(Context mContext, String basic) {
//creating the itemApi interface
ItemApi itemApi = retrofit.create(ItemApi.class);
//making the call object
Call<List<Item>> call = itemApi.checkItems(basic);
call.enqueue(new Callback<List<Item>>() {
@Override
public void onResponse(@NonNull Call<List<Item>> call,
@NonNull Response<List<Item>> response) {
if (response.isSuccess()) {
List<Item> itemList;
itemList = response.body();
int dataSize = response.body().size();
Log.d(TAGGG, String.valueOf(dataSize));
itemList.forEach(List -> Log.d(TAGGG, String.valueOf(List.getEan())));
itemList.forEach(List -> Log.d(TAGGG, String.valueOf(List.getNo())));
class DownloadTask extends AsyncTask<String, Integer, String> {
// Runs in UI before background thread is called
@Override
protected void onPreExecute() {
super.onPreExecute();
// Do something like display a progress bar
}
// This is run in a background thread
@Override
protected String doInBackground(String... params) {
// Do something that takes a long time, for example:
for (int i = 0; i <= 3 ; i++) {
try (DatabaseHandler itemsManager = new DatabaseHandler((XXXXApp)
mContext.getApplicationContext())) {
itemList.stream().limit(1500).forEach(item -> {
itemsManager.addItem(item);
itemsManager.close();
});
}
// Call this to update your progress
publishProgress(i);
}
return "this string is passed to onPostExecute";
}
// This is called from background thread but runs in UI
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
// Do things like update the progress bar
}
// This runs in UI when background thread finishes
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// Do things like hide the progress bar or change a TextView
}
}
new DownloadTask().execute();
}
}
@Override
public void onFailure(Call<List<Item>> call, Throwable t) {}
});
return;
}
但是,结果并不令人满意,因为数据库没有正确下载;我将 i 的值更改为 9 并将 .limit() 的值更改为 500(以实现相同的结果,即下载 +4.500 项),结果相同。
问题肯定出在这段代码中:
for (int i = 0; i <= 3 ; i++) {
try (DatabaseHandler itemsManager = new DatabaseHandler((XXXApp)
mContext.getApplicationContext()))
{
itemList.stream().limit(1500).forEach(item -> {
itemsManager.addItem(item);
itemsManager.close();
});
}
// Call this to update your progress
publishProgress(i);
}
这是我在大量谷歌搜索后找到的最接近我想要实现的方法;问题当然是每次关闭数据库并重新打开它的 For-Loop;我也不确定 SQlite 数据库的数据量是否太大;因此,非常感谢任何有关如何正确解决此问题的帮助或提示,谢谢!
- Create once instance of DatabaseHandler(what is it? you can use room with more comfortable API) and reuse it.
- Insert many(100-500) items in one transaction.
或者您可以在服务器端创建 sqlite 数据库文件,然后下载它并在 android 应用程序中作为数据库打开。