我在Android应用中使用Retrofit2和Rxjava2作为网络库,并在NodeJS和MongoDB中将其用作后端服务。我想从服务器获取数据并将数据存储在会议室数据库中,以便用户再次打开应用时获取数据直到服务器上添加了一些新数据后,才从房间而不是服务器上获取数据。
到目前为止,我已经成功地从服务器获取了数据并将其显示在回收站视图中。
我想要实现的目标:
1)从服务器获取数据后,将数据存储在会议室数据库中。
2)显示会议室数据库中的数据,直到服务器上更新了一些新数据。
这是我的下面的代码:
ApiService.java
public interface ApiService {
@POST("retrofitUsers")
@FormUrlEncoded
Observable<String> saveData(@Field("name") String name,
@Field("age") String age);
@GET("getUsers")
Observable<List<BioData>> getData();
}
RetrofitClient.java
public class RetrofitClient {
private static Retrofit retrofit = null;
public static Retrofit getInstance(){
if(retrofit == null)
retrofit = new Retrofit.Builder()
.baseUrl("https://bookbudiapp.herokuapp.com/")
.addConverterFactory(GsonConverterFactory.create(new GsonBuilder().setLenient().create()))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
return retrofit;
}
private RetrofitClient(){
}
}
BioData.java
public class BioData {
@SerializedName("name")
@Expose
private String name;
@SerializedName("age")
@Expose
private String age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
}
MainActivity.java
public class Users extends AppCompatActivity {
RecyclerView recycle;
UserAdapter adapter;
List<BioData> list;
CompositeDisposable compositeDisposable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recycle = findViewById(R.id.recycle);
recycle.setHasFixedSize(true);
recycle.setLayoutManager(new LinearLayoutManager(this));
list = new ArrayList<>();
compositeDisposable = new CompositeDisposable();
fetchData();
}
private void fetchData(){
Retrofit retrofit = RetrofitClient.getInstance();
ApiService myApi = retrofit.create(ApiService.class);
Disposable disposable = myApi.getData().subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<List<BioData>>() {
@Override
public void accept(List<BioData> bioData) throws Exception {
adapter = new UserAdapter(bioData,getApplicationContext());
recycle.setAdapter(adapter);
}
});
compositeDisposable.add(disposable);
}
@Override
protected void onStop() {
super.onStop();
compositeDisposable.clear();
}
}
如何在我的应用程序中添加Room数据库,让我知道我对此一无所知。
谢谢
答案 0 :(得分:3)
房间基础
Room库充当基础SQLite数据库的抽象层。因此,使用了房间注释:
会议室中有3个主要组成部分
Entity:带有@Entity注释的类被映射到数据库中的表。每个实体都保存在自己的表中,类中的每个字段都代表列名。
tableName属性用于定义表的名称 每个实体类必须至少有一个主键字段,并用@PrimaryKey注释 实体类中的字段可以使用@ColumnInfo(name =“ name_of_column”)注释进行注释,以给出特定的列名
DAO:数据访问对象可以是带有@Doa批注的接口或抽象类,其中包含定义用于对数据执行的操作的所有方法。可以使用
@查询以从数据库检索数据
@插入以将数据插入数据库
@Delete从数据库中删除数据
@Update以更新数据库中的数据
添加这些依赖项:
dependencies {
// Room dependencies
compile 'android.arch.persistence.room:runtime:1.0.0'
annotationProcessor 'android.arch.persistence.room:compiler:1.0.0'
}
创建实体
在创建数据库之前,我们先创建一个名为Note的实体,然后将此类的对象添加到数据库中。
@Entity
public class Note {
@PrimaryKey(autoGenerate = true)
private int note_id;
@ColumnInfo(name = "note_content") // column name will be "note_content" instead of "content" in table
private String content;
private String title;
private
public Note(int note_id, String content, String title) {
this.note_id = note_id;
this.content = content;
this.title = title;
}
public int getNote_id() {
return note_id;
}
public void setNote_id(int note_id) {
this.note_id = note_id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Note)) return false;
Note note = (Note) o;
if (note_id != note.note_id) return false;
return title != null ? title.equals(note.title) : note.title == null;
}
@Override
public int hashCode() {
int result = note_id;
result = 31 * result + (title != null ? title.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "Note{" +
"note_id=" + note_id +
", content='" + content + '\'' +
", title='" + title + '\'' +
'}';
}}
创建DAO
DAO定义了所有访问数据库的方法,并带有@Dao注释。 DAO充当对数据库中的数据执行CRUD操作的合同。
@Dao
public interface NoteDao {
@Query("SELECT * FROM user "+ Constants.TABLE_NAME_NOTE)
List<Note> getAll();
/*
* Insert the object in database
* @param note, object to be inserted
*/
@Insert
void insert(Note note);
/*
* update the object in database
* @param note, object to be updated
*/
@Update
void update(Note repos);
/*
* delete the object from database
* @param note, object to be deleted
*/
@Delete
void delete(Note note);
/*
* delete list of objects from database
* @param note, array of objects to be deleted
*/
@Delete
void delete(Note... note); // Note... is varargs, here note is an array
}
创建数据库
现在,我们已将表定义为通过NoteDao定义的Entity和CRUD方法。数据库难题的最后一部分是数据库本身。
@Database(entities = { Note.class }, version = 1)
public abstract class NoteDatabase extends RoomDatabase {
public abstract NoteDao getNoteDao();
private static NoteDatabase noteDB;
public static NoteDatabase getInstance(Context context) {
if (null == noteDB) {
noteDB = buildDatabaseInstance(context);
}
return noteDB;
}
private static NoteDatabase buildDatabaseInstance(Context context) {
return Room.databaseBuilder(context,
NoteDatabase.class,
Constants.DB_NAME)
.allowMainThreadQueries().build();
}
public void cleanUp(){
noteDB = null;
}
}
实现数据库交互
下面的代码片段将演示使用Room数据库进行插入,更新和删除功能的过程。
public class AddNoteActivity extends AppCompatActivity {
private TextInputEditText et_title,et_content;
private NoteDatabase noteDatabase;
private Note note;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_note);
et_title = findViewById(R.id.et_title);
et_content = findViewById(R.id.et_content);
noteDatabase = NoteDatabase.getInstance(AddNoteActivity.this);
Button button = findViewById(R.id.but_save);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// fetch data and create note object
note = new Note(et_content.getText().toString(),
et_title.getText().toString());
// create worker thread to insert data into database
new InsertTask(AddNoteActivity.this,note).execute();
}
});
}
private void setResult(Note note, int flag){
setResult(flag,new Intent().putExtra("note",note));
finish();
}
private static class InsertTask extends AsyncTask<Void,Void,Boolean> {
private WeakReference<AddNoteActivity> activityReference;
private Note note;
// only retain a weak reference to the activity
InsertTask(AddNoteActivity context, Note note) {
activityReference = new WeakReference<>(context);
this.note = note;
}
// doInBackground methods runs on a worker thread
@Override
protected Boolean doInBackground(Void... objs) {
activityReference.get().noteDatabase.getNoteDao().insertNote(note);
return true;
}
// onPostExecute runs on main thread
@Override
protected void onPostExecute(Boolean bool) {
if (bool){
activityReference.get().setResult(note,1);
}
}
}
}
检索并显示记事列表
public class NoteListActivity extends AppCompatActivity implements NotesAdapter.OnNoteItemClick{
private TextView textViewMsg;
private RecyclerView recyclerView;
private NoteDatabase noteDatabase;
private List<Note> notes;
private NotesAdapter notesAdapter;
private int pos;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initializeVies();
displayList();
}
private void displayList(){
// initialize database instance
noteDatabase = NoteDatabase.getInstance(NoteListActivity.this);
// fetch list of notes in background thread
new RetrieveTask(this).execute();
}
private static class RetrieveTask extends AsyncTask<Void,Void,List<Note>>{
private WeakReference<NoteListActivity> activityReference;
// only retain a weak reference to the activity
RetrieveTask(NoteListActivity context) {
activityReference = new WeakReference<>(context);
}
@Override
protected List<Note> doInBackground(Void... voids) {
if (activityReference.get()!=null)
return activityReference.get().noteDatabase.getNoteDao().getNotes();
else
return null;
}
@Override
protected void onPostExecute(List<Note> notes) {
if (notes!=null && notes.size()>0 ){
activityReference.get().notes = notes;
// hides empty text view
activityReference.get().textViewMsg.setVisibility(View.GONE);
// create and set the adapter on RecyclerView instance to display list
activityReference.get().notesAdapter = new NotesAdapter(notes,activityReference.get());
activityReference.get().recyclerView.setAdapter(activityReference.get().notesAdapter);
}
}
}
private void initializeVies(){
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
textViewMsg = (TextView) findViewById(R.id.tv\_\_empty);
// Action button to add note
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(listener);
recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(NoteListActivity.this));
}
}
更新说明
public class AddNoteActivity extends AppCompatActivity {
private TextInputEditText et_title,et_content;
private NoteDatabase noteDatabase;
private Note note;
private boolean update;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_note);
et_title = findViewById(R.id.et_title);
et_content = findViewById(R.id.et_content);
noteDatabase = NoteDatabase.getInstance(AddNoteActivity.this);
Button button = findViewById(R.id.but_save);
if ( (note = (Note) getIntent().getSerializableExtra("note"))!=null ){
getSupportActionBar().setTitle("Update Note");
update = true;
button.setText("Update");
et_title.setText(note.getTitle());
et_content.setText(note.getContent());
}
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
note.setContent(et_content.getText().toString());
note.setTitle(et_title.getText().toString());
noteDatabase.getNoteDao().updateNote(note);
}
});
}
}
删除记事
noteDatabase.getNoteDao().deleteNote(notes.get(pos));
adapterObj.notifyDataSetChanged();
答案 1 :(得分:0)
Android开发人员为Room提供了一个很好的入门教程:https://developer.android.com/training/data-storage/room/index.html
对于要添加的功能,最好使用存储库模式。为简单起见,“存储库模式”就像是应用程序和服务器之间的类,您在其中询问一些数据(例如用户名),而应用程序不知道该数据来自何处(数据库或服务器)。存储库将执行以下操作:
class UserRepository {
public User getUser() {
User user = db.userDao().getUser() //Room sintax
if(user==null){
//access to server and get user object
db.userDao().insert(user)
}
return db.userDao().getUser()
}
}
这允许应用程序解耦,例如,如果您想将来更改服务器,则只需更改存储库类,其余的应用程序将相同。我建议您调查一下。您还应该使用存储库应实现的接口,这样可以使耦合解耦更多