首先定义一个User类:
// 定义为Entity
@Entity
public class User {
// 设置主键
@PrimaryKey(autoGenerate = true)
private int uid;
private String name;
// 提供setter和getter供Room框架调用
public User(String name) {
this.name = name;
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User:" + name + ", uid=" + uid;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
if (uid != user.uid) return false;
return name != null ? name.equals(user.name) : user.name == null;
}
@Override
public int hashCode() {
int result = uid;
result = 31 * result + (name != null ? name.hashCode() : 0);
return result;
}
}
接下来是创建数据库:
// 声明为Database,指定表格、版本
@Database(entities = {User.class}, version = 1, exportSchema = false)
public abstract class MyDatabase extends RoomDatabase {
private static MyDatabase sInstance;
// 构造函数必须是public,否则报错
public MyDatabase() {
}
// 单实例模式,节省资源
public static MyDatabase getsInstance(Context context) {
if (sInstance == null) {
synchronized (MyDatabase.class) {
if (sInstance == null) {
sInstance = Room.databaseBuilder(context.getApplicationContext(),
MyDatabase.class, "sampleDb").build();
}
}
}
return sInstance;
}
// 定义获取Dao的方法
abstract UserDao userDao();
}
定义数据存取对象:
@Dao
public interface UserDao {
@Insert
void insert(User user);
@Query("SELECT * FROM user")
LiveData> users();
}
然后ViewModel就可以从Dao中获取LiveData了:
public class MainViewModel extends AndroidViewModel {
private final UserDao mUserDao;
private static final String TAG = "MainViewModel";
private final LiveData> mUsers;
public MainViewModel(@NonNull Application application) {
super(application);
mUserDao = MyDatabase.getsInstance(application).userDao();
mUsers = mUserDao.users();
}
public UserDao getUserDao(){
return mUserDao;
}
public LiveData> getUsers() {
return mUsers;
}
}
定义Holder和Adapter:
public class UserHolder extends RecyclerView.ViewHolder {
public final TextView mText;
public UserHolder(View itemView) {
super(itemView);
mText = itemView.findViewById(android.R.id.text1);
}
}
public class UserAdapter extends RecyclerView.Adapter<UserHolder> {
private static final String TAG = "UserAdapter";
private List mUsers = new ArrayList<>();
public void setList(List users) {
mUsers = users;
}
@NonNull
@Override
public UserHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
return new UserHolder(inflater.inflate(android.R.layout.simple_list_item_1, parent, false));
}
@Override
public void onBindViewHolder(@NonNull UserHolder holder, int position) {
holder.mText.setText(mUsers.get(position).toString());
}
@Override
public int getItemCount() {
return mUsers.size();
}
}
activity_main.xml:
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="add"
android:text="add"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<EditText
android:id="@+id/et"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/add"
app:layout_constraintTop_toTopOf="parent"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layoutManager="android.support.v7.widget.LinearLayoutManager"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/et"/>
android.support.constraint.ConstraintLayout>
MainActivity:
public class MainActivity extends AppCompatActivity {
private EditText mInput;
private RecyclerView mRecyclerView;
private MainViewModel mViewModel;
private UserAdapter mUserAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mInput = findViewById(R.id.et);
mRecyclerView = findViewById(R.id.recycler);
mUserAdapter = new UserAdapter();
mRecyclerView.setAdapter(mUserAdapter);
// 获取ViewModel
mViewModel = ViewModelProviders.of(this).get(MainViewModel.class);
// 观察ViewModel中的LiveData的变化
mViewModel.getUsers().observe(this, new Observer>() {
@Override
public void onChanged(@Nullable List users) {
mUserAdapter.setList(users);
mUserAdapter.notifyDataSetChanged();
mRecyclerView.smoothScrollToPosition(mUserAdapter.getItemCount() - 1);
}
});
}
public void add(View view) {
// 子线程中进行数据库插入
final Disposable disposable = Completable.fromAction(new Action() {
@Override
public void run() {
mViewModel.getUserDao().insert(new User(mInput.getText().toString()));
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action() {
@Override
public void run() throws Exception {
mInput.getText().clear();
}
});
}
}
在上一个例子的基础上进行修改:
首先是Dao类中数据列表不再直接返回LiveData
,而是返回DataSource.Factory
:
@Dao
public interface UserDao {
@Insert
void insert(User user);
@Query("SELECT * FROM user")
DataSource.Factory users();
}
public class MainViewModel extends AndroidViewModel {
private final UserDao mUserDao;
private static final String TAG = "MainViewModel";
// LiveData的泛型不是单纯的User,还包装了一层PagedList
private final LiveData> mUsers;
public MainViewModel(@NonNull Application application) {
super(application);
// 根据Dao中返回的DataSource构造LiveData,可以在LivePagedListBuilder中添加回调
mUsers = new LivePagedListBuilder<>(mUserDao.users(), 15)
.build();
}
public UserDao getUserDao() {
return mUserDao;
}
public LiveData> getUsers() {
return mUsers;
}
}
Adapter此时需要继承自PagedListAdapter
,无需实现getItemCount()
方法,也无需提供方法传入数据列表:
public class UserAdapter extends PagedListAdapter<User, UserHolder> {
private static final String TAG = "UserAdapter";
// 需要提供DiffUtil的实现来比对Item
protected UserAdapter() {
super(new DiffUtil.ItemCallback() {
@Override
public boolean areItemsTheSame(User oldItem, User newItem) {
return oldItem.getUid() == newItem.getUid();
}
@Override
public boolean areContentsTheSame(User oldItem, User newItem) {
return oldItem.equals(newItem);
}
});
}
@NonNull
@Override
public UserHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
return new UserHolder(inflater.inflate(android.R.layout.simple_list_item_1, parent, false));
}
@Override
public void onBindViewHolder(@NonNull UserHolder holder, int position) {
holder.mText.setText(getItem(position).toString());
}
}
使用PagedListAdapter自带的submitList更新数据列表:
public class MainActivity extends AppCompatActivity {
private EditText mInput;
private RecyclerView mRecyclerView;
private MainViewModel mViewModel;
private UserAdapter mUserAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mInput = findViewById(R.id.et);
mRecyclerView = findViewById(R.id.recycler);
mUserAdapter = new UserAdapter();
mRecyclerView.setAdapter(mUserAdapter);
mViewModel = ViewModelProviders.of(this).get(MainViewModel.class);
mViewModel.getUsers().observe(this, new Observer>() {
@Override
public void onChanged(@Nullable PagedList users) {
// 使用PagedListAdapter自带的submitList更新数据列表
mUserAdapter.submitList(users);
}
});
public void add(View view) {
...
}
}