【问题标题】:How to fill spinner with data from Room without blocking UI thread如何在不阻塞 UI 线程的情况下用 Room 中的数据填充微调器
【发布时间】:2019-02-10 19:07:17
【问题描述】:

我已经在一个表格中预先填充了一个带有运动队名称的 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();
    }

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

【问题讨论】:

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


    【解决方案1】:

    根据 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;
        }
    }
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多