mrm*_*aan 0 sqlite android arraylist android-room
背景: 我正在尝试为纸牌游戏构建一个牌组构建器。不同的牌组基于我想要在本地保护的一个数组列表。这意味着你可以创建你的牌组,然后我希望你能够保护它,然后创建一个新的牌组,能够再次保存它... ->这会产生我想要在同一个类中保护的多个 Arraylists 。
问题: 在知道我想要的不仅仅是一个 Arraylist 的情况下,将 Arraylist 存储在 Room 中的最佳方式是什么?
据我现在所知,我必须创建一个实体类,它基本上会创建一个(?)表,我必须在其中逐个保存Arraylists?
有更好的方法吗?
奖励: 我也希望有一个关于如何做到这一点的基本示例,因为这似乎是我自己很难实现的。
非常感谢!
编辑:
代码示例
因此,我使用您的代码示例的基线实现的内容如下:
我创建了 SaveDeck 类,它应该能够使用给定的 Deckname 保存 Deck : :-
@Entity 公共类 SaveDeck 实现可序列化 { @PrimaryKey(autoGenerate = true) 私有 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;
Run Code Online (Sandbox Code Playgroud)
}
我创建了 Dao 类,如下所示::-
@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);
Run Code Online (Sandbox Code Playgroud)
}
进一步创建了DataBase类:
@Database(entities = {SaveDeck.class}, version = 1) 公共抽象类 SaveDecksDataBase 扩展 RoomDatabase { 公共抽象 DeckBuilderDao DeckBuilderDao(); }
最后尝试在我各自的片段中创建设置,这就是我挣扎的地方::-
公共类 review_fragment 扩展 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();
}
Run Code Online (Sandbox Code Playgroud)
}
所以现在我不知道如何正确地将新实例添加到我的 Class 中SaveDeck。我习惯使用带有构造函数的数组列表。因此我就这样尝试了。您能看一下并帮我一下吗?
在知道我想要的不仅仅是一个 Arraylist 的情况下,将 Arraylist 存储在 Room 中的最佳方法是什么?
可以说没有办法是最好的办法。
ArrayList 不只是出现,数据和元素结构(如果每个元素存在多个值)来自某个地方,也就是说,它们只是容器,而不是分组数据的持久容器。由于最终结果似乎是持久的结构化数据集,因此主要利用数据库可能会更简单。
我正在尝试为纸牌游戏构建 Deckbuilder。不同的牌组基于我想要在本地保护的一个数组列表。
听起来这是卡牌的基础,即可用于游戏的卡牌。所以听起来您想要在数据库中为卡片建立一个表。
这意味着你可以创建你的牌组,然后我希望你能够保护它,然后创建一个新的牌组,
听起来您想要在数据库中为牌组提供一个表格,并且一副牌可以有一个卡片列表。那么有多少张卡呢?10、20、3000?好吧,如果您利用关系数据库管理器(SQLite 和 Room(因为后者是 SQLite 上的抽象层))的关系功能。因此,很可能存在所谓的映射(同一事物的引用、关系和其他名称)表。
这主要存储由可以标识关系的一部分的列和可以标识另一部分的另一列组成的关系。将其应用到您的情况中,一副牌将与许多牌有关系,一张牌可能会出现在许多牌组中。这是映射表所满足的多对多关系。所以您可能需要一个映射表。
为了进一步解释,假设我们正在谈论扑克牌(黑桃 A、红心皇后等)。
因此,我们需要三个表: Card表、Deck表和将纸牌映射到牌组的表(反之亦然)Card_Deck_Map表。
为了简单起见,Card表将有一个单独的卡名列。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
;
Run Code Online (Sandbox Code Playgroud)
上面的输出将是:-
首先是 3 个实体使用 Room 实体定义数据
:-
@Entity (indices = {@Index(value = {"cardname"}, unique = true)})
public class Card {
@PrimaryKey(autoGenerate = true)
public long _id;
@ColumnInfo(name = "cardname")
public String cardname;
}
Run Code Online (Sandbox Code Playgroud)
:-
@Entity(indices = {@Index(value = "deckname", unique = true)})
public class Deck {
@PrimaryKey(autoGenerate = true)
public long _id;
@ColumnInfo(name = "deckname")
public String deckname;
}
Run Code Online (Sandbox Code Playgroud)
:-
@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;
}
Run Code Online (Sandbox Code Playgroud)
现在您需要数据访问对象定义使用 Room DAO 访问数据
:-
@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();
Run Code Online (Sandbox Code Playgroud)
}
将实体和 DAO 连接在一起的数据库类
:-
@Database(entities = {Card.class, Deck.class, Card_Deck_Map.class}, version = 1)
public abstract class DeckBuilderDatabase extends RoomDatabase {
public abstract DeckBuilderDao deckBuilderDao();
}
Run Code Online (Sandbox Code Playgroud)
现在是使用数据库的活动。
在这个工作示例中;
数据库将填充 2 副牌(Deck001 和 Deck002),每副扑克牌减去小丑牌作为一个牌库。
牌组将装载一些卡牌(映射)
Decks 和 Cards 将从数据库中提取并用于填充 ListView。
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;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6570 次 |
| 最近记录: |