Сохранение нескольких Arraylist в базе данных комнаты - лучший способ сделать это?

-3

Предыстория: я пытаюсь построить Deckbuilder для карточной игры. Различные колоды основаны на одном Arraylists, которые я хочу сохранить на месте. Это означает, что вы можете создать свою колоду, а затем я хочу, чтобы вы смогли ее сохранить, а затем создать новую колоду, чтобы сохранить ее снова... → Это дает несколько Arraylists, которые я хочу сохранить в одном классе,

Вопрос: Каков наилучший способ хранения Arraylists в комнате, зная, что я хочу, чтобы не только один Arraylist пришел?

Из того, что я знаю сейчас, это то, что я должен создать класс сущностей, который в основном создаст мне одну (?) Таблицу, где мне придется сохранять Arraylists друг за другом?

Есть ли лучший способ сделать это.

Бонус: мне бы очень понравился базовый пример того, как это сделать, так как это кажется мне очень сложным.

Спасибо большое!

Редактировать:

Пример кода

Итак, что я реализовал с помощью базовой линии из вашего примера кода:

  1. Я создал класс SaveDeck, который должен иметь возможность сохранять колоду с заданным именем колоды:: -

    Открытый класс @Entity SaveDeck реализует Serializable {@PrimaryKey (autoGenerate = true) private int _id;

    public SaveDeck(int _id, String deckName, int cardImage, int typeImage, Integer cardCost, String cardName, Integer cardNumber) {
        this._id = _id;
        DeckName = deckName;
        CardImage = cardImage;
        TypeImage = typeImage;
        CardCost = cardCost;
        CardName = cardName;
        CardNumber = cardNumber;
    }
    
    @ColumnInfo(name = "DeckName")
    private String DeckName;
    
    @ColumnInfo(name = "CardImage")
    private int CardImage;
    
    @ColumnInfo(name = "TypeImage")
    private int TypeImage;
    
    @ColumnInfo(name = "CardCost")
    private Integer CardCost;
    
    @ColumnInfo(name = "CardName")
    private String CardName;
    
    @ColumnInfo(name = "CardNumber")
    private Integer CardNumber;
    

    }

  2. Я создал класс Дао следующим образом:

    @Dao публичный интерфейс DeckBuilderDao {

    @Insert(onConflict = OnConflictStrategy.IGNORE)
    public long[] insertCards(SaveDeck... saveDecks);
    
    @Insert(onConflict = OnConflictStrategy.IGNORE)
    public long insertCard(SaveDeck saveDecks);
    
    @Update
    public int updateCardBaseEntries(SaveDeck... saveDecks);
    
    @Update
    public int updateCardBaseEntry(SaveDeck saveDecks);
    
    @Delete
    public int deleteCardBaseEntried(SaveDeck... saveDecks);
    
    @Delete
    public int deleteCardBaseEntry(SaveDeck saveDecks);
    
    @Query("SELECT * FROM SaveDeck")
    public SaveDeck[] getAllDecks();
    
    //probably I do not need the getAllDecks Query. Right now I only need the following one:
    @Query("SELECT * FROM SaveDeck WHERE DeckName = :NameOfDeck ORDER  BY DeckName, CardName")
    public SaveDeck getOneDeck(String NameOfDeck);
    

    }

  3. Кроме того, создал класс базы данных:

    @Database (entity = {SaveDeck.class}, version = 1) открытый абстрактный класс SaveDecksDataBase extends RoomDatabase {открытый абстрактный DeckBuilderDao deckBuilderDao(); }

  4. В конце концов попытался создать настройки в моем соответствующем фрагменте, вот где я борюсь:

    public class review_fragment extends Fragment {

    private List<TransferDeck> mTransferDeck = DataHolder.getInstance().savedDecklistTransfer;
    SaveDecksDataBase mSavedDecksDB;
    Cursor mCursor;
    
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    //return super.onCreateView(inflater, container, savedInstanceState);
        View view = inflater.inflate(R.layout.review_fragment, container, false);
    
        /*Introduce Cards Recycler*/
    
        RecyclerView rvCards = view.findViewById(R.id.rv_review_cardlist);
        rvCards.setLayoutManager(new GridLayoutManager(getActivity(), 5));
        review_RViewAdapter_Cards adapterCards = new review_RViewAdapter_Cards(getContext(), mTransferDeck);
        rvCards.setAdapter(adapterCards);
    
    
    
        /*Init Room database*/
        mSavedDecksDB = Room.databaseBuilder(getActivity(),SaveDecksDataBase.class,"SavedDecksDB.db").build();
        populateDB(mTransferDeck);
    
    
    
    
    
        return view;
    }
    
    private void populateDB(final List<TransferDeck> mTransferDeck) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                List<SaveDeck> mSaveDeck = new ArrayList<>();
                for(int i = 0; i<mTransferDeck.size(); i++){
                    mSaveDeck.add(new SaveDeck(i, "FirstSavedDeck", mTransferDeck.get(i).getCardImage() ,mTransferDeck.get(i).getTypeImage(), mTransferDeck.get(i).getCost(), mTransferDeck.get(i).getName(), mTransferDeck.get(i).getNumber()));
                }
                mSavedDecksDB.deckBuilderDao().insertCards(mSaveDeck);
    
            }
        }).start();
    }
    

    }

Так что сейчас я не знаю, как правильно добавлять новые экземпляры в мой класс SaveDeck. Я привык использовать Arraylists, с конструкторами. Поэтому я попробовал это так. Не могли бы вы взглянуть на это и помочь мне, пожалуйста?

  • 0
    Посмотрите на многие отношения и таблицы соединений, чтобы получить представление о том, как организовать вещи.
  • 0
    Спасибо брат. Я проверяю ответ decend ниже. Вы знаете, почему я получил отрицательные голоса :(
Теги:
arraylist
android-room

1 ответ

0
Лучший ответ

Каков наилучший способ хранения Arraylists в комнате, зная, что я хочу, чтобы не только один Arraylist пришел?

Возможно, нет лучшего пути.

ArrayList не просто появляется, данные и структура элемента (если существует несколько значений на элемент) откуда-то, то есть они являются просто контейнерами, а не постоянными контейнерами сгруппированных данных. Поскольку конечный результат представляет собой устойчивые структурированные наборы данных, вероятно, было бы проще использовать базу данных в первую очередь.

Я пытаюсь построить Deckbuilder для карточной игры. Различные колоды основаны на одном Arraylists, которые я хочу сохранить на месте.

Казалось бы, это основа карт, то есть доступных для игры. Похоже, вы хотите таблицу в базе данных для карт.

Это означает, что вы можете создать свою колоду, а затем я хочу, чтобы вы смогли ее сохранить, а затем создать новую колоду,

Это звучит, как вы хотите таблицу в базе данных для палуб и что колода может иметь список карт. Так сколько карт? 10, 20, 3000? Хорошо, если вы используете возможности отношений Realational Database Manager (который является SQLite и, следовательно, Room (так как последний является абстрактным слоем над SQLite)). Таким образом, вполне вероятно, что это то, что известно как таблица сопоставления (ссылки, отношения и другие имена для одной и той же вещи).

Это прежде всего хранит отношения, которые состоят из столбца, который может идентифицировать одну часть отношения, и другого столбца, который может идентифицировать другую часть. Примените это к вашему случаю, когда DECK будет иметь отношение к нескольким картам, CARD может появиться в нескольких DECK. Это многоплановое отношение, которое обслуживает таблица сопоставления. Таким образом, вы, вероятно, хотите таблицу сопоставления.

В качестве основы для дальнейшего объяснения будем предполагать, что речь идет об игральных картах (Ace of Spades, Queen of Hearts и т.д.).

Таким образом, мы хотим, чтобы три таблицы карточного стола, стол на палубу и таблицы, которая отображает карты колоды (и, следовательно, наоборот) в таблицу Card_Deck_Map.

Для простоты таблицы карт будет один столбец для имени карты. Таблицы Deck будут иметь один столбец для названия колоды. Для эффективности будет использован идентификатор, который является псевдонимом специального столбца rowid для отображения. Таким образом, в каждой из приведенных выше таблиц будет дополнительный столбец, который будет называться _id (при названии столбца _id это может быть полезно для Android).

Предполагается, что вы не хотите, чтобы название карты или название колоды дублировались, и поэтому будут применены УНИКАЛЬНЫЕ ограничения, которые не позволят дублировать имена.

Чтобы кратко изложить здесь, как это может выглядеть в SQL (что, в конечном счете, и делает большинство хранилищ, манипуляций и извлечения данных):

-- Delete the tables if they exist (just in case)
DROP TABLE IF EXISTS card_deck_map;
DROP TABLE IF EXISTS card;
DROP TABLE IF EXISTS deck;

-- Create the tables
CREATE TABLE IF NOT EXISTS card (_id INTEGER PRIMARY KEY, cardname UNIQUE);
CREATE TABLE IF NOT EXISTS deck (_id INTEGER PRIMARY KEY, deckname UNIQUE);
CREATE TABLE IF NOT EXISTS card_deck_map (
    card_reference INTEGER REFERENCES card(_id), 
    deck_reference INTEGER REFERENCES deck(_id),
    PRIMARY KEY(card_reference,deck_reference)
);

-- Add 3 cards to the card table
INSERT INTO card (cardname) VALUES ('CARD001'),('CARD002'),('CARD003');
-- Add 3 decks to the deck table
INSERT INTO deck (deckname) VALUES ('DECK001'),('DECK002');
-- Create some mapping entries (aka put some cards into each deck)
INSERT INTO card_deck_map VALUES
    (1,2), -- _id value for CARD001 should be 1, _id value for DECK002 should be 2
    (3,2), -- CARD003 is in DECK002
    (2,1), -- CARD002 is in DECK001
    (1,1) -- CARD001 is also in DECK002
;
-- Have a look at what we have (ignore the id values they mean little to the user)
SELECT deckname, cardname 
FROM deck 
    JOIN card_deck_map ON deck._id = deck_reference
    JOIN card ON card_deck_map.card_reference = card._id
ORDER BY deckname, cardname
;

Выход из вышеупомянутого будет:

Изображение 166961

Таким образом, теперь дизайн базы данных подходит, и теперь он может быть преобразован для использования в ROOM.

Сначала 3 объекта Определение данных с использованием объектов Room

Card.java

: -

@Entity (indices = {@Index(value = {"cardname"}, unique = true)})
public class Card {
    @PrimaryKey(autoGenerate = true)
    public long _id;

    @ColumnInfo(name = "cardname")
    public String cardname;

}

Deck.java

: -

@Entity(indices = {@Index(value = "deckname", unique = true)})
public class Deck {

    @PrimaryKey(autoGenerate = true)
    public long _id;

    @ColumnInfo(name = "deckname")
    public String deckname;
}

Card_Deck_Map.java

: -

@Entity(
        primaryKeys = {"card_reference","deck_reference"},
        foreignKeys = {
                @ForeignKey(entity = Card.class,parentColumns = "_id",childColumns = "card_reference"),
                @ForeignKey(entity = Deck.class, parentColumns = "_id",childColumns = "deck_reference")}
                )
public class Card_Deck_Map {

    @ColumnInfo (name="card_reference")
    public long card_reference;

    @ColumnInfo(name="deck_reference")
    public long deck_reference;
}

Теперь вам нужны определения объектов доступа к данным Доступ к данным с использованием комнатных DAO

DeckBuildeDao

: -

@Dao публичный интерфейс DeckBuilderDao {

@Insert(onConflict = OnConflictStrategy.IGNORE)
public long[] insertCards(Card... cards);

@Insert(onConflict = OnConflictStrategy.IGNORE)
public long insertCard(Card card);

@Update
public int updateCardBaseEntries(Card... cards);

@Update
public int updateCardBaseEntry(Card card);

@Delete
public int deleteCardBaseEntried(Card... cards);

@Delete
public int deleteCardBaseEntry(Card card);

@Query("SELECT * FROM card")
public Card[] getAllCards();

@Query("SELECT * FROM card WHERE _id = :id")
public Card getACard(long id);



@Insert(onConflict = OnConflictStrategy.IGNORE)
public long[] insertDecks(Deck... decks);

@Insert(onConflict = OnConflictStrategy.IGNORE)
public long insertDeck(Deck deck);

@Update
public int updateDeckEntries(Deck... decks);

@Update
public int updateDeckEntry(Deck deck);

@Delete
public int deleteDeckEntries(Deck... decks);

@Delete
public int deleteDeckEntry(Deck deck);

@Query("SELECT * FROM deck")
public int getAllDecks();

@Query("SELECT * FROM deck WHERE _id = :id")
public Deck getADeck(long id);


@Insert(onConflict = OnConflictStrategy.IGNORE)
public long[] addCardDeckEntries(Card_Deck_Map... cardDeckMaps);

@Insert(onConflict = OnConflictStrategy.IGNORE)
public long addCardDeckEntry(Card_Deck_Map cardDeckMap);

@Query("SELECT Deck._id,Card.cardname, Deck.deckname " +
        "FROM deck " +
        "JOIN card_deck_map ON deck._id = card_deck_map.deck_reference " +
        "JOIN card ON card_deck_map.card_reference = card._id " +
        "ORDER BY deckname, cardname")
public Cursor getAllDecksWithCards();

}

Класс для базы данных, который связывает сущности и DAO вместе

DeckBuilderDatabase.java

: -

@Database(entities = {Card.class, Deck.class, Card_Deck_Map.class}, version = 1)
public abstract class DeckBuilderDatabase extends RoomDatabase {
    public abstract DeckBuilderDao deckBuilderDao();
}

Теперь деятельность, которая использует базу данных.

В этом рабочем примере;

  1. база данных будет заполнена 2 колодами (Deck001 и Deck002) с карточной базой согласно колоду игральных карт за вычетом джокеров.

    1. Карты будут называться как Ace of Spades, 2 of Hearts.
  2. Колоды будут загружены некоторыми картами (карта)

    1. Deck002 со всеми 52 картами.
    2. Deck001 с 3 картами.
  3. Колоды и карты будут извлечены из базы данных и использованы для заполнения ListView.

MainActivity.java

public class MainActivity extends AppCompatActivity {

    public static final String[] SUITS = new String[]{"Spades","Hearts","Clubs","Diamons"};
    public static final int CARDS_IN_A_SUIT = 13;


    DeckBuilderDatabase mDBDB;
    SimpleCursorAdapter mSCA;
    ListView mDecks_and_Cards_List;
    Cursor mCursor;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mDecks_and_Cards_List = this.findViewById(R.id.decksandcards);
        mDBDB = Room.databaseBuilder(this,DeckBuilderDatabase.class,"deckbuilder.db").build();
        populateDB();
    }

    /**
     * Populate the DB with some data, extract the data in the DB and setup the ListView
     */
    private void populateDB() {
        new Thread(new Runnable() {
            @Override
            public void run() {

                Card_Deck_Map currentcdm = new Card_Deck_Map();

                Deck[] decks_to_add = new Deck[]{new Deck(), new Deck()};
                decks_to_add[0].deckname = "DECK001";
                decks_to_add[1].deckname= "DECK002";
                mDBDB.deckBuilderDao().insertDecks(decks_to_add);

                // Build Card base pack of 52 (no Jokers)
                Card[] cardstoadd = new Card[CARDS_IN_A_SUIT * SUITS.length];
                int counter = 0;
                for (int suit = 0; suit < SUITS.length; suit++) {
                    for (int cardval = 0; cardval < CARDS_IN_A_SUIT; cardval++) {
                        Card thiscard = new Card();
                        String thiscardname = generateCardValueDescription(cardval+1,suit);
                        thiscard.cardname = thiscardname;
                        cardstoadd[counter++] = thiscard;
                    }
                }
                mDBDB.deckBuilderDao().insertCards(cardstoadd);

                // Populate the decks with cards Deck002 has full pack of 52 Deck001 has 3 cards
                Card_Deck_Map[] mappings = new Card_Deck_Map[55];
                for (int cardid = 1; cardid < 53; cardid++) {
                    Card_Deck_Map cdm = new Card_Deck_Map();
                    cdm.deck_reference = 2;
                    cdm.card_reference = cardid;
                    mappings[cardid-1] = cdm;
                }
                Card_Deck_Map cdm53 = new Card_Deck_Map();
                cdm53.card_reference = 19;
                cdm53.deck_reference = 1;
                mappings[52] = cdm53;
                Card_Deck_Map cdm54 = new Card_Deck_Map();
                cdm54.card_reference = 10;
                cdm54.deck_reference = 1;
                mappings[53] = cdm54;
                Card_Deck_Map cdm55 = new Card_Deck_Map();
                cdm55.card_reference = 23;
                cdm55.deck_reference = 1;
                mappings[54] = cdm55;
                mDBDB.deckBuilderDao().addCardDeckEntries(mappings);

                // Get the Decks and cards in the decks
                mCursor = mDBDB.deckBuilderDao().getAllDecksWithCards();
                setupOrRefeshListView();
            }
        }).start();
    }


    /**
     * Handles the ListView (also write data to the log for debugging)
     */
    private void setupOrRefeshListView() {
        int rowcount = mCursor.getCount();
        Log.d("ROWS","Number of rows in the Cursor is " + String.valueOf(rowcount));
        while (mCursor.moveToNext()) {
            Log.d(
                    "ROWS",
                    "Row " +
                            String.valueOf(mCursor.getPosition()) +
                            " Has a deck called " +
                            mCursor.getString(mCursor.getColumnIndex("deckname")) +
                            " and a card called " +
                            mCursor.getString(mCursor.getColumnIndex("cardname"))
            );
        }
        if (mSCA == null) {
            mSCA = new SimpleCursorAdapter(
                    this,
                    android.R.layout.simple_list_item_2,
                    mCursor,
                    new String[]{
                            "deckname",
                            "cardname"},
                    new int[]{
                            android.R.id.text1,
                            android.R.id.text2},
                    0
            );
            mDecks_and_Cards_List.setAdapter(mSCA);
        } else {
            mSCA.swapCursor(mCursor);
        }
    }

    /**
     *  Converts numeric cardvalue (1-13) and suit to a decriptive name
     * @param cardvalue
     * @param suit
     * @return
     */
    private String generateCardValueDescription(int cardvalue, int suit) {
        String rv;
        switch (cardvalue) {
            case 1:
                rv = "Ace of " + SUITS[suit];
                break;
            case 11:
                rv = "Jack of " + SUITS[suit];
                break;
            case 12:
                rv = "Queen of " + SUITS[suit];
                break;
            case 13:
                rv = "King of " + SUITS[suit];
                break;
                default:
                    rv = String.valueOf(cardvalue) + " of " + SUITS[suit];
        }
        return rv;
    }
}

Результирующее мини-приложение: -

Изображение 166962

  • 0
    Спасибо MikeT. Я проверяю ваш ответ как можно скорее, возможно, завтра. Я хотел бы дать вам очки, которые я мог!
  • 0
    Привет, Майк, мои настройки немного отличаются. Я постараюсь все еще использовать это. Я уже собрал фрагмент, который позволяет мне в основном собрать вашу колоду . Я загружаю предварительный просмотр всех карт в Recyclerview. Все карты уже хранятся в разных таблицах в (SQlite) БД. Если вы выбираете карту для своей колоды, создается новая запись в Arraylist. Мой план состоял в том, чтобы спасти этого Arraylist. В общем, мне не нужно создавать новый банк данных для моих карт, он уже существует. Я просто хочу сохранить свой Arraylist, поэтому я не думаю, что есть необходимость в картографическом столе. :)
Показать ещё 6 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню