1. 添加依赖库
//for lifecycle and LiveData and ViewModel
implementation "android.arch.lifecycle:runtime:$archRuntimeVersion"
implementation "android.arch.lifecycle:extensions:$archExtensionVersion"
annotationProcessor "android.arch.lifecycle:compiler:$archVersion"
implementation "android.arch.persistence.room:runtime:$archVersion"
annotationProcessor "android.arch.persistence.room:compiler:$archVersion"
// Paging
implementation "android.arch.paging:runtime:1.0.1"
2. 数据库实体类编写
@Entity()
public class Cheese {
@PrimaryKey(autoGenerate = true)
@NonNull
public int id;
public String name;
public Cheese(String name) {
this.name = name;
}
}
3. 数据库dao接口编写
@Dao
public interface CheeseDao {
@Query("SELECT * FROM cheese ORDER BY name COLLATE NOCASE ASC")
DataSource.Factory allCheesesByName();
@Insert
void insertList(List cheeses);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(Cheese cheese);
@Delete
void delete(Cheese cheese);
}
4. 数据库类编写
@Database(entities = {Cheese.class}, version = 1, exportSchema = false)
public abstract class CheeseDb extends RoomDatabase {
public abstract CheeseDao cheeseDao();
@VisibleForTesting
public static final String DATABASE_NAME = "cheese.db";
private static CheeseDb INSTANCE;
public static CheeseDb getDatabase(final Context context) {
if (INSTANCE == null) {
synchronized (CheeseDb.class) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
CheeseDb.class, DATABASE_NAME)
.fallbackToDestructiveMigration()
.addCallback(callback)
.build();
}
}
}
return INSTANCE;
}
private static RoomDatabase.Callback callback = new RoomDatabase.Callback() {
@Override
public void onOpen(@NonNull SupportSQLiteDatabase db) {
super.onOpen(db);
new PopulateDbAsync(INSTANCE).execute();
}
};
private static class PopulateDbAsync extends AsyncTask {
private final CheeseDao mDao;
PopulateDbAsync(CheeseDb db) {
mDao = db.cheeseDao();
}
@Override
protected Void doInBackground(Void... voids) {
ArrayList list = new ArrayList<>();
// 假数据
for (String name : data) {
list.add(new Cheese(name));
}
mDao.insertList(list);
return null;
}
}
public static final String[] data = {"Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi",
"Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu", "Airag", "Airedale",
"Aisy Cendre", "Allgauer Emmentaler", "Alverca", "Ambert", "American Cheese",
"Ami du Chambertin", "Anejo Enchilado", "Anneau du Vic-Bilh", "Anthoriro", "Appenzell",
"Aragon", "Ardi Gasna", "Ardrahan", "Armenian String", "Aromes au Gene de Marc",
"Asadero", "Asiago", "Aubisque Pyrenees", "Autun", "Avaxtskyr", "Baby Swiss",
"Babybel", "Baguette Laonnaise", "Bakers", "Baladi", "Balaton", "Bandal", "Banon",
"Barry's Bay Cheddar", "Basing", "Basket Cheese", "Bath Cheese", "Bavarian Bergkase",
"Baylough", "Beaufort", "Beauvoorde", "Beenleigh Blue", "Beer Cheese", "Bel Paese",
"Bergader", "Bergere Bleue", "Berkswell", "Beyaz Peynir", "Bierkase", "Bishop Kennedy",
"Blarney", "Bleu d'Auvergne", "Bleu de Gex", "Bleu de Laqueuille",
"Bleu de Septmoncel", "Bleu Des Causses", "Blue", "Blue Castello", "Blue Rathgore",
"Blue Vein (Australian)", "Blue Vein Cheeses", "Bocconcini", "Bocconcini (Australian)",
"Boeren Leidenkaas", "Bonchester", "Bosworth", "Bougon", "Boule Du Roves",
"Boulette d'Avesnes", "Boursault", "Boursin", "Bouyssou", "Bra", "Braudostur",
"Breakfast Cheese", "Brebis du Lavort", "Brebis du Lochois", "Brebis du Puyfaucon",
"Bresse Bleu", "Brick", "Brie", "Brie de Meaux", "Brie de Melun", "Brillat-Savarin",
"Brin", "Brin d' Amour", "Brin d'Amour", "Brinza (Burduf Brinza)",
"Briquette de Brebis", "Briquette du Forez", "Broccio", "Broccio Demi-Affine",
"Brousse du Rove", "Bruder Basil", "Brusselae Kaas (Fromage de Bruxelles)", "Bryndza",
"Buchette d'Anjou", "Buffalo", "Burgos", "Butte", "Butterkase", "Button (Innes)",
"Buxton Blue", "Cabecou", "Caboc"};
}
5. ViewModel类编写
public class CheeseViewModel extends AndroidViewModel {
private final CheeseDao mCheeseDao;
public final LiveData> listLiveData;
public CheeseViewModel(@NonNull Application application) {
super(application);
mCheeseDao = CheeseDb.getDatabase(application).cheeseDao();
listLiveData = new LivePagedListBuilder<>(mCheeseDao.allCheesesByName(),
new PagedList.Config.Builder()
.setPageSize(30)
.setEnablePlaceholders(true)
.build())
.build();
}
public void insert(final String text) {
Executors.newSingleThreadExecutor().execute(new Runnable() {
@Override
public void run() {
mCheeseDao.insert(new Cheese(text));
}
});
}
public void remove(final Cheese cheese) {
Executors.newSingleThreadExecutor().execute(new Runnable() {
@Override
public void run() {
mCheeseDao.delete(cheese);
}
});
}
}
6. 分页设配器类编写ViewHolder 和 Adapter
public class CheeseViewHolder extends RecyclerView.ViewHolder {
private TextView tvName;
public Cheese cheese;
public CheeseViewHolder(@NonNull View itemView) {
super(itemView);
tvName = itemView.findViewById(R.id.name);
}
public void bindTo(Cheese cheese) {
this.cheese = cheese;
tvName.setText(cheese.name);
}
}
public class CheeseAdapter extends PagedListAdapter {
private static DiffUtil.ItemCallback ITEM_CALLBACK = new DiffUtil.ItemCallback() {
@Override
public boolean areItemsTheSame(@NonNull Cheese oldItem, @NonNull Cheese newItem) {
return oldItem.id == newItem.id;
}
@Override
public boolean areContentsTheSame(@NonNull Cheese oldItem, @NonNull Cheese newItem) {
return oldItem.name.equals(newItem.name);
}
};
public CheeseAdapter() {
super(ITEM_CALLBACK);
}
@NonNull
@Override
public CheeseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int i) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.cheese_item, parent, false);
return new CheeseViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull CheeseViewHolder holder, int position) {
holder.bindTo(getItem(position));
}
}
7. Activity 及页面布局编写
public class MainActivity extends AppCompatActivity {
private CheeseViewModel viewModel;
private CheeseAdapter adapter;
private RecyclerView recyclerView;
private Button btnAdd;
private EditText etText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.cheeseList);
btnAdd = findViewById(R.id.addButton);
etText = findViewById(R.id.inputText);
viewModel = ViewModelProviders.of(this).get(CheeseViewModel.class);
adapter = new CheeseAdapter();
recyclerView.setAdapter(adapter);
viewModel.listLiveData.observe(this, new Observer>() {
@Override
public void onChanged(@Nullable PagedList cheeses) {
adapter.submitList(cheeses);
}
});
initListener();
initSwipeToDelete();
}
private void initSwipeToDelete() {
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new ItemTouchHelper.Callback() {
@Override
public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
return makeMovementFlags(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT);
}
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder viewHolder1) {
return false;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
if (viewHolder instanceof CheeseViewHolder) {
CheeseViewHolder holder = (CheeseViewHolder) viewHolder;
viewModel.remove(holder.cheese);
}
}
});
itemTouchHelper.attachToRecyclerView(recyclerView);
}
private void initListener() {
btnAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
addCheese();
}
});
etText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
addCheese();
return true;
}
return false;
}
});
etText.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_ENTER) {
addCheese();
return true;
}
return false;
}
});
}
private void addCheese() {
String cheese = etText.getText().toString().trim();
if (!TextUtils.isEmpty(cheese)) {
viewModel.insert(cheese);
etText.setText("");
}
}
}
管理线程执行工具类
public class AppExecutors {
private final Executor mDiskIO;
private final Executor mNetworkIO;
private final Executor mMainThread;
private AppExecutors(Executor diskIO, Executor networkIO, Executor mainThread) {
this.mDiskIO = diskIO;
this.mNetworkIO = networkIO;
this.mMainThread = mainThread;
}
public AppExecutors() {
this(Executors.newSingleThreadExecutor(), Executors.newFixedThreadPool(3),
new MainThreadExecutor());
}
public Executor diskIO() {
return mDiskIO;
}
public Executor networkIO() {
return mNetworkIO;
}
public Executor mainThread() {
return mMainThread;
}
private static class MainThreadExecutor implements Executor {
private Handler mainThreadHandler = new Handler(Looper.getMainLooper());
@Override
public void execute(@NonNull Runnable command) {
mainThreadHandler.post(command);
}
}
}