#java #android #android-room
Вопрос:
Я внедряю локальную базу данных, используя ROOM в Android studio. У меня возникла проблема. Я успешно вставляю и удаляю записи данных в базу данных. Но когда я получаю все объекты данных из базы данных, то каждый раз получаю на один объект меньше. Когда начинается это действие, проблем нет, но когда я пытаюсь обновить представление переработчика после вставки нового объекта данных в базу данных, этот объект обновляется в представлении переработчика на один шаг после создания новой записи объекта данных, и с этим также возникает та же проблема.
ниже приведен мой полный код:-
package com.example.eventus.DashBoard;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.DialogFragment;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.app.AlertDialog;
import android.app.DatePickerDialog;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.Toast;
import com.example.eventus.ApplicationDatabase.Events.Event;
import com.example.eventus.ApplicationDatabase.Events.EventsAdapter;
import com.example.eventus.ApplicationDatabase.Events.EventsDao;
import com.example.eventus.R;
import com.example.eventus.Singletons.DatabaseSingleton;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
public class Dashboard extends AppCompatActivity implements View.OnClickListener, DatePickerDialog.OnDateSetListener {
//Declaring the views
private FloatingActionButton fbAddEvent;
private Button btnOKNewEvent, btnCancelNewEvent;
private EditText etDeadlineNewEvent, etTitleNewEvent, etInfoNewEvent;
//For recycler view
private RecyclerView rvEvents;
private RecyclerView.LayoutManager layoutManager;
private List<Event> events;
private EventsAdapter eventsAdapter;
//For alert box
private AlertDialog.Builder alertDialogBuilder;
private AlertDialog alertDialog;
private View alertDialogView;
//For database
private DatabaseSingleton databaseSingleton;
private EventsDao eventsDao;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dashboard);
//Initializing and setting onclicklisteners on views
init();
//RecyclerView stuff
recyclerViewStuff();
//new event stuff
newEventDialog();
//database stuff
database();
//loadEvents
loadEvents();
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.fb_add_event_dashboard:
alertDialog.show();
}
}
@Override
public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
Calendar mCalendar = Calendar.getInstance();
mCalendar.set(Calendar.YEAR, year);
mCalendar.set(Calendar.MONTH, month);
mCalendar.set(Calendar.DAY_OF_MONTH, dayOfMonth);
String selectedDate = DateFormat.getDateInstance(DateFormat.FULL).format(mCalendar.getTime());
etDeadlineNewEvent.setText(selectedDate);
}
private void init(){
//Initializing the views
rvEvents = findViewById(R.id.rv_events_dashboard);
fbAddEvent = findViewById(R.id.fb_add_event_dashboard);
//Setting onclicklisteners on views
fbAddEvent.setOnClickListener(this);
}
private void recyclerViewStuff() {
//Initializing the recycler view stuffs
layoutManager = new GridLayoutManager(this, 2);
rvEvents.setLayoutManager(layoutManager);
}
private void newEventDialog() {
alertDialogBuilder = new AlertDialog.Builder(Dashboard.this);
alertDialogView = getLayoutInflater().inflate(R.layout.new_event, null);
alertDialogBuilder.setView(alertDialogView);
alertDialog = alertDialogBuilder.create();
alertDialog.setCanceledOnTouchOutside(false);
//Instantiating the view
btnOKNewEvent = alertDialogView.findViewById(R.id.btn_ok_new_event);
etDeadlineNewEvent = alertDialogView.findViewById(R.id.et_deadline_new_event);
btnCancelNewEvent = alertDialogView.findViewById(R.id.btn_cancel_new_event);
etTitleNewEvent = alertDialogView.findViewById(R.id.et_title_new_event);
etInfoNewEvent = alertDialogView.findViewById(R.id.et_info_new_event);
//setting on click listeners for the views in dialog box
btnOKNewEvent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
addEvent();
//loadEvents();
refreshEvents();
alertDialog.dismiss();
}
});
btnCancelNewEvent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
alertDialog.dismiss();
}
});
etDeadlineNewEvent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
DialogFragment datePicker = new com.example.eventus.DateAndTime.DatePicker();
datePicker.show(getSupportFragmentManager(), null);
}
});
}
private void database(){
//getting the database instance
databaseSingleton = DatabaseSingleton.getInstance();
//getting the events dao
eventsDao = databaseSingleton.getEventsDao(getApplicationContext());
//deleting all previously saved events
eventsDao.deleteAllEvent();
}
private void addEvent() {
String eventTitle, eventInfo, eventDeadline;
eventTitle = etTitleNewEvent.getText().toString();
eventInfo = etInfoNewEvent.getText().toString();
eventDeadline = etDeadlineNewEvent.getText().toString();
//creating an event
Event event = new Event(eventTitle, eventInfo, eventDeadline);
Handler handler = new Handler();
Runnable runnable = new Runnable() {
@Override
public void run() {
eventsDao.createEvent(event);
Toast.makeText(Dashboard.this, "Event Created", Toast.LENGTH_SHORT).show();
}
};
handler.post(runnable);
}
private void loadEvents(){
events = eventsDao.getEvents();
eventsAdapter = new EventsAdapter(events);
rvEvents.setAdapter(eventsAdapter);
}
private void refreshEvents(){
events.clear();
List<Event> tempEventsList = eventsDao.getEvents();
for(int i=0;i<tempEventsList.size();i ){
events.add(tempEventsList.get(i));
}
eventsAdapter.notifyDataSetChanged();
}
}
Комментарии:
1. очевидно, что вы не загружаетесь после вставки … очевидно, потому
addEvent
что не добавляет событие, а просто добавляет очередь в основной поток … похоже, вы не знаете, что делает данный метод, и используете его … это нехорошо — вы должны понимать свой код
Ответ №1:
Проблема, с которой вы столкнулись, связана с параллелизмом. Если вы проверяете свой код, вы сначала вызываете метод add event и помещаете вставку внутри выполняемого, это указывает приложению на выполнение в более позднее время, когда это возможно, но оно не выполняет его немедленно; для этого код продолжает выполнение, вы извлекаете события, а затем, позже, добавляется новое событие.
Чтобы решить вашу проблему, попробуйте поместить вызов метода refreshEvents внутри выполняемого.
Runnable runnable = new Runnable() {
@Override
public void run() {
eventsDao.createEvent(event);
Toast.makeText(Dashboard.this, "Event Created", Toast.LENGTH_SHORT).show();
refreshEvents();
}
};
handler.post(runnable);
РЕДАКТИРОВАТЬ: Как правильно сказано в комментариях, это не проблема с несколькими потоками, это время выполнения фрагментов кода внутри одного потока.
Комментарии:
1. Проблема, с которой вы столкнулись, связана с параллелизмом параллелизма ? здесь нет параллелизма … параллелизм-это когда вызывается более одного потока
2. Вставки и извлечения из базы данных являются асинхронными операциями. Когда вы делаете экземпляр интерфейса доступным для выполнения, вы фактически создаете новый поток, который недоедает. docs.oracle.com/javase/7/docs/api/java/lang/Runnable.html
3. Когда вы делаете экземпляр интерфейса доступным для выполнения, вы фактически создаете новый поток, который вы сделали в мой день
… нет, это неправда … Запускаемый не имеет ничего общего с новым потоком — это просто то, что можно запустить ….
4. У меня возникла проблема, связанная с асинхронной операцией, возникшей из-за моей ошибки: -)
5. в то время как код в ответе поможет вашей интерпретации неверен … Есть основная нить … и
onClick
публикуется для выполнения в этой теме … когда вы используете другойpost
внутриonClick
, то этот запускаемый объект будет выполнен ПОСЛЕ всего кода внутриonClick
… здесь нет асинхронного кода