各位!今天,我试图解决下一个问题:我为语言列表创建了空间数据库,为不同的语言预先填充了五个就绪对象,然后尝试将它们转换为spinner适配器,如下所示:
Language
对象的实体和DAO代码:
@Entity
public class Language {
@PrimaryKey
private long id;
@ColumnInfo(name = "language")
private String language;
public Language(String language) {
this.language = language;
}
public static Language[] populateData() {
return new Language[]{new Language("English"), new Language("French"), new Language(
"Spanish"), new Language("Russian"), new Language("Italian")};
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
}
@Dao
public interface LanguageDao {
@Query("SELECT * FROM language")
List<Language> getAll();
@Insert
void insertAll(Language... languages);
}
此外,我在AppDatabase
类中使用Singleton创建了数据库对象,如下所示:
@Database(entities = {Language.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
private static AppDatabase INSTANCE;
public abstract LanguageDao languageDao();
public synchronized static AppDatabase getInstance(Context context) {
if (INSTANCE == null) {
INSTANCE = buildDatabase(context);
}
return INSTANCE;
}
private static AppDatabase buildDatabase(final Context context) {
return Room.databaseBuilder(context, AppDatabase.class, "my-database")
.addCallback(new Callback() {
@Override
public void onCreate(@NonNull SupportSQLiteDatabase db) {
super.onCreate(db);
Executors.newSingleThreadScheduledExecutor().execute(new Runnable() {
@Override
public void run() {
getInstance(context).languageDao()
.insertAll(Language.populateData());
}
});
}
})
.allowMainThreadQueries()
.build();
}
}
如您所见,我已经将语言对象的预填充数据插入到数据库实例中。我知道这里不推荐使用allowMainThreadQueries()
方法(只需使用它来简化当前的培训)。
此外,我还创建了以下方法,它返回spinner对象并将其放入活动代码中:
private Spinner createLanguageSpinner(){
Spinner spinner = findViewById(R.id.language_spinner);
List<Language> languages = AppDatabase.getInstance(this).languageDao().getAll();
List<String>languageStrings = new LinkedList<>();
for(int i = 0; i < languages.size(); i++){
languageStrings.add(languages.get(i).getLanguage());
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_dropdown_item_1line,
languageStrings);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
return spinner;
}
我的问题是:
List<Language> languages = AppDatabase.getInstance(this).languageDao().getAll();
我无法用预定义的对象填充当前列表,这将导致没有选项可选的空自旋器。你能告诉我哪里弄错了吗?我还想听听关于如何简化适配器创建的意见。
发布于 2019-01-15 19:18:55
我去派对有点晚了,但万一有人也有这个问题。
问题是,您试图插入没有PrimaryKey id
值的新对象。因此,您将在数据库中得到一个空表。
您可以手动设置id
值,例如:
@Entity
public class Language {
...
public Language(long id, String language) {
this.id = id; // or create method to generate a unique id as a PrimaryKey value must be unique
this.language = language;
}
public static Language[] populateData() {
return new Language[]{
new Language(1, "English"),
new Language(2, "French"),
new Language(3, "Spanish"),
new Language(4, "Russian"),
new Language(5, "Italian")
};
}
}
或者使用PrimaryKey的PrimaryKey属性让SQLite生成唯一的id:
@PrimaryKey(autoGenerate = true)
private long id;
有关更多信息,请参见参考文献。
不需要对代码进行任何其他更改。
回答第二个问题:
我还想听听关于如何简化适配器创建的意见。
您可以为您的旋转器创建一个自定义适配器,并将一个List<Language>
直接传递给它:
public class MyAdapter extends BaseAdapter implements SpinnerAdapter {
private LayoutInflater mInflater;
private List<Language> mItems;
public MyAdapter(Context context, List<Language> items) {
mInflater = LayoutInflater.from(context);
mItems = items;
}
@Override
public int getCount() {
return mItems.size();
}
@Override
public Object getItem(int position) {
return mItems.get(position);
}
@Override
public long getItemId(int position) {
return mItems.get(position).getId();
}
// This is for the default ("idle") state of the spinner.
// You can use a custom layout or use the default one.
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (view == null) {
view = mInflater.inflate(R.layout.spinner_item, parent, false);
}
Language item = (Language) getItem(position);
TextView textView = view.findViewById(R.id.text);
textView.setText(item.getTitle());
return view;
}
// Drop down item view as stated in the method name.
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (view == null) {
view = mInflater.inflate(R.layout.spinner_dropdown_item, parent, false);
}
Language item = (Language) getItem(position);
TextView textView = view.findViewById(R.id.text);
textView.setText(item.getTitle());
return view;
}
}
在你的活动中:
List<Language> languages = AppDatabase.getInstance(this).languageDao().getAll();
Spinner spinner = findViewById(R.id.spinner);
MyAdapter myAdapter = new MyAdapter(this, languages);
spinner.setAdapter(myAdapter);
请参阅BaseAdapter和SpinnerAdapter参考。
或者您可以使用ArrayAdapter
并简单地重写对象的toString
方法,以确定列表(参考文献)中的项将显示什么文本:
@Entity
public class Language {
...
@NonNull
@Override
public String toString() {
// A value you want to be displayed in the spinner item.
return language;
}
}
在你的活动中:
List<Language> languages = AppDatabase.getInstance(this).languageDao().getAll();
Spinner spinner = findViewById(R.id.spinner);
// Pass your list as the third parameter. No need to convert it to List<String>
ArrayAdapter<Language> adapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line, languages);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
https://stackoverflow.com/questions/49157770
复制相似问题