Получение на один объект меньше из базы данных КОМНАТ

#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 … здесь нет асинхронного кода