如何在不阻止UI线程的情况下用Room中的数据填充微调框

时间:2019-02-10 19:07:17

标签: android android-asynctask android-spinner android-room executor

我已经在表格中预先填充了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();
    }

我希望该活动加载有用Teams表中的团队名称填充的微调器,但是应用程序在显示活动之前崩溃,并显示与不允许在主线程上运行查询相关的错误。

1 个答案:

答案 0 :(得分:0)

根据android文档,您必须使用存储库来填充用户界面。

这是我的代码,其中包含一个来自简单房间实体的示例微调器。

我的实体。

@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;
    }
}

我的小岛,请小心返回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();
            }
        });

    }