[英]How to fill spinner with data from Room without blocking UI thread
我已经在一个表中预先填充了一个带有运动队名称的 Android Room 数据库。 我想用这些名称在下面的活动中填充一个微调器。 我还需要运行几个类似的任务,并且不能为此使用主线程。 如何使用 asynctask 或 executor 执行此操作?
这些数据不是实时的,不会改变,但会被调用来填充几个不同的小部件。
`//Activity`
public class RegisterPlayers extends AppCompatActivity {
public static PlayerRegistryDatabase playerRegistryDatabase;
`@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register_players);
createTeamsSpinner();
}
private Spinner createTeamsSpinner() {
Spinner spinner = findViewById(R.id.rank1);
List<Teams> teamName = PlayerRegistryDatabase.getInstance(this).playerRegistryDao().getAllTeams();
List<String> teamNameStrings = new LinkedList<>();
for (int i = 0; i < teamName.size(); i++) {
teamNameStrings.add(teamName.get(i).getTeamName());
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_dropdown_item_1line,
teamNameStrings);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
return spinner;
}
}
`
`//Teams Class`
@Entity
`public class Teams {private String conferenceName;`
@PrimaryKey@NonNull
private String teamName;
public Teams(String conferenceName, String teamName) {
this.conferenceName = conferenceName;
this.teamName = teamName;
}
public String getConferenceName() {
return conferenceName;
}
public void setConferenceName(String conferenceName) {
this.conferenceName = conferenceName;
}
public String getTeamName() {
return teamName;
}
public void setTeamName(String teamName) {
this.teamName = teamName;
}
public static Teams[] populateData() {
return new Teams[] {
new Teams("W", "Panthers"),
new Teams("W", "Eagles"),
new Teams("E", "Bulldogs"),
new Teams("E", "Cheetahs"),
};
}`
`//Dao`
`@Dao
public interface PlayerRegistryDao {`
@Insert
void insertAll(Teams... teamName);
@Query("SELECT * FROM Teams")
List<Teams> getAllTeams();
`}`
`//Database`
@Database(entities = {PlayerRegistry.class, Teams.class}, version = 1, exportSchema = false)
`public abstract class PlayerRegistryDatabase extends RoomDatabase {`
private static PlayerRegistryDatabase buildDatabase(final Context context) {
return Room.databaseBuilder(context,
PlayerRegistryDatabase.class,
"teams")
.addCallback(new Callback() {
@Override
//@NonNull error, tried android support option
public void onCreate(@NonNull SupportSQLiteDatabase db) {
super.onCreate(db);
Executors.newSingleThreadScheduledExecutor().execute(new Runnable() {
@Override
public void run() {
getInstance(context).playerRegistryDao().insertAll(Teams.populateData());
}
});
}
})
.build();
}
我希望活动加载时使用填充有团队表中的团队名称的微调器,但应用程序在显示活动之前崩溃,并出现与不允许在主线程上运行的查询相关的错误。
根据 android 文档,您必须使用存储库来填充您的 ui。
这是我的代码,其中包含从简单房间实体填充的示例微调器。
我的实体。
@Entity(tableName = Category.TABLE_NAME)
public class Category implements Parcelable {
//constructor setters and getters
protected Category(Parcel in) {
id = in.readLong();
name = in.readString();
}
public static final Creator<Category> CREATOR = new Creator<Category>() {
@Override
public Category createFromParcel(Parcel in) {
return new Category(in);
}
@Override
public Category[] newArray(int size) {
return new Category[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(id);
dest.writeString(name);
}
/** The name of the Cheese table. */
public static final String TABLE_NAME = "category";
/** The name of the ID column. */
public static final String COLUMN_ID = BaseColumns._ID;
/** The name of the name column. */
public static final String COLUMN_NAME = "name";
@PrimaryKey(autoGenerate = true)
@ColumnInfo(index = true, name = COLUMN_ID)
private long id;
@ColumnInfo(name = COLUMN_NAME)
private String name;
public Category(){
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
我的 dao,负责返回 LiveData。
@Dao
public interface CategoryDao {
@Query("SELECT COUNT(*) FROM " + Category.TABLE_NAME)
LiveData<Integer> count();
@Insert
long insert(Category category);
@Query("SELECT * FROM " +Category.TABLE_NAME)
LiveData<List<Category>> selectAll();
@Query("DELETE FROM " + Category.TABLE_NAME + " WHERE " + Category.COLUMN_ID + " = :id")
int deleteById(long id);
@Update
int update(Category item);
@Delete
public void delete(Category item);
}
存储库,根据 android 最佳实践。
public class CategoryRepository {
private CategoryDao mDao;
private LiveData<List<Category>> allItems;
public CategoryRepository(Application application) {
AppDatabase db = AppDatabase.getInstance(application);
mDao = db.categoryDao();
allItems = mDao.selectAll();
}
public LiveData<List<Category>> getAll() {
return allItems;
}
public void insert(Category item) {
new InsertAsyncTask(mDao).execute(item);
}
public void update(Category item) {
new UpdateAsyncTask(mDao).execute(item);
}
public void delete(Category item) {
new DeleteAsyncTask(mDao).execute(item);
}
private static class InsertAsyncTask extends AsyncTask<Category, Void, Void> {
private CategoryDao asyncTaskDao;
InsertAsyncTask(CategoryDao dao) {
asyncTaskDao = dao;
}
@Override
protected Void doInBackground(final Category... params) {
asyncTaskDao.insert(params[0]);
return null;
}
}
private static class UpdateAsyncTask extends AsyncTask<Category, Void, Void> {
private CategoryDao asyncTaskDao;
UpdateAsyncTask(CategoryDao dao) {
asyncTaskDao = dao;
}
@Override
protected Void doInBackground(final Category... params) {
asyncTaskDao.update(params[0]);
return null;
}
}
private static class DeleteAsyncTask extends AsyncTask<Category, Void, Void> {
private CategoryDao asyncTaskDao;
DeleteAsyncTask(CategoryDao dao) {
asyncTaskDao = dao;
}
@Override
protected Void doInBackground(final Category... params) {
asyncTaskDao.delete(params[0]);
return null;
}
}
}
从存储库填充代码。 我们到了,这是最后一步,你明白了!
private void loadSpinnerData() {
// database handler
CategoryRepository categoryRepository = new CategoryRepository(getActivity().getApplication());
// Creating adapter for spinner
final ArrayAdapter<Category> dataAdapter = new ArrayAdapter<Category>(getActivity(),
android.R.layout.simple_spinner_item, new ArrayList<Category>(0));
// Drop down layout style - list view with radio button
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// attaching data adapter to spinner
editCategorySpinner.setAdapter(dataAdapter);
categoryRepository.getAll().observe(this, new Observer<List<Category>>() {
@Override
public void onChanged(@Nullable final List<Category> items) {
// tri de la liste
Collections.sort(items, new Comparator<Category>() {
public int compare(Category obj1, Category obj2) {
// ## Ascending order
return obj1.getName().compareToIgnoreCase(obj2.getName());
}
});
// ajout dans la list et refresh
dataAdapter.addAll(items);
dataAdapter.notifyDataSetChanged();
}
});
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.