В настоящее время я играю с Android - Room Persistence Library и пытаюсь получить не живые данные из базы данных SQLite, которые затем необходимо обработать и проверить по данным из Firestore Cloud. Все это выполняется в AsyncTask, но когда я пытаюсь получить данные из Room, я получаю следующую ошибку: "java.lang.IllegalStateException: не удается получить доступ к базе данных в главном потоке, так как он может потенциально заблокировать пользовательский интерфейс на длительный период времени.".
Я понимаю, что я не могу вызвать метод базы данных из основного потока, но все это вызывается из AsyncTask, который должен обрабатывать все, что я сказал выше. Что я делаю не так?
Я попытался создать asyncTask в моем MainRepository, который в короткие сроки выглядит так:
public List<Shift> getAllShiftsForJobExport(int jobId){
try {
return new GetShiftsForJobAsync(shiftDao).execute(jobId).get();
} catch (ExecutionException e) {
e.printStackTrace();
return null;
} catch (InterruptedException e) {
e.printStackTrace();
return null;
}
}
Это не сработало все время и в итоге дало некоторые измотанные результаты ...
Моя AsyncTask, где я пытаюсь извлечь данные из комнаты и сравнить с облаком Firestore, выглядит так:
private static class DownloadDataFromCloud extends AsyncTask<Void, Void, Void> {
private CloudViewModel viewModel;
private FirebaseFirestore db;
private String userId;
DownloadDataFromCloud(FragmentActivity activity){
viewModel = ViewModelProviders.of(activity).get(CloudViewModel.class);
}
private void downloadData(){
List<Job> jobs = viewModel.getAllJobs();
Map<String, Job> jobDocuments = new HashMap<>();
for(Job job : jobs){
if(job.getDocumentId() != null){
jobDocuments.put(job.getDocumentId(), job);
}
}
CollectionReference jobsCollection = db.collection("jobs");
jobsCollection.whereEqualTo("userId", userId)
.get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
@Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
for(QueryDocumentSnapshot documentSnapshot : queryDocumentSnapshots){
Job job = new Job();
job.convertCloudToObject(documentSnapshot);
if(jobDocuments.containsKey(job.getDocumentId())){
job.setId(jobDocuments.get(job.getDocumentId()).getId());
viewModel.updateJob(job);
downloadShiftData(job.getId(), job.getDocumentId());
}else {
viewModel.insertJobWithReturn(job, new AsyncResponse<Long>() {
@Override
public void processFinish(Long output) {
long jobId = output;
downloadShiftData((int) jobId, job.getDocumentId());
}
});
}
}
}
});
}
private void downloadShiftData(int jobId, String documentId){
List<Shift> shifts = viewModel.getAllShiftForJob(jobId);
Map<String, Shift> shiftDocuments = new HashMap<>();
for(Shift shift : shifts){
if(shift.getDocumentId() != null){
shiftDocuments.put(shift.getDocumentId(), shift);
}
}
CollectionReference shiftCollection = db.collection("shifts");
shiftCollection.whereEqualTo("userId", userId)
.whereEqualTo("jobDocumentId", documentId)
.get().addOnSuccessListener(queryDocumentSnapshots -> {
for (QueryDocumentSnapshot documentSnapshot : queryDocumentSnapshots) {
Shift shift = new Shift();
shift.convertCloudToObject(documentSnapshot);
if(shiftDocuments.containsKey(shift.getDocumentId())){
shift.setId(shiftDocuments.get(shift.getDocumentId()).getId());
viewModel.updateShift(shift);
}else {
shift.setJobId(jobId);
viewModel.insertShift(shift);
}
}
});
}
@Override
protected Void doInBackground(Void... voids) {
downloadData();
return null;
}
@Override
protected void onPreExecute() {
db = FirebaseFirestore.getInstance();
userId = FirebaseAuth.getInstance().getUid();
super.onPreExecute();
}
@Override
protected void onCancelled() {
super.onCancelled();
}
}
Полная трассировка стека, которую я получаю:
java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
at androidx.room.RoomDatabase.assertNotMainThread(RoomDatabase.java:228)
at androidx.room.RoomDatabase.query(RoomDatabase.java:255)
at androidx.room.util.DBUtil.query(DBUtil.java:54)
at com.*.daos.ShiftDao_Impl.getAllShiftsForJobExport(ShiftDao_Impl.java:909)
at com.*.MainRepository.getAllShiftsForJobExport(MainRepository.java:203)
at com.*.CloudViewModel.getAllShiftForJob(CloudViewModel.java:33)
at com.*.CloudHandler$DownloadDataFromCloud.downloadShiftData(CloudHandler.java:216)
at com.*.CloudHandler$DownloadDataFromCloud.access$300(CloudHandler.java:171)
at com.*.CloudHandler$DownloadDataFromCloud$1.onSuccess(CloudHandler.java:200)
at com.*.CloudHandler$DownloadDataFromCloud$1.onSuccess(CloudHandler.java:190)
at com.google.android.gms.tasks.zzn.run(Unknown Source:4)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Редактировать - код для GetShiftsForJobAsync:
private static class GetShiftsForJobAsync extends AsyncTask<Integer, Void, List<Shift>>{
private ShiftDao shiftDao;
GetShiftsForJobAsync(ShiftDao shiftDao){
this.shiftDao = shiftDao;
}
@Override
protected List<Shift> doInBackground(Integer... integers) {
return shiftDao.getAllShiftsForJobExport(integers[0]);
}
}