How to store data in room database after fetching from server

后端 未结 2 1823
予麋鹿
予麋鹿 2021-01-03 07:58

I am using Retrofit2 and Rxjava2 in my android app as a networking library and NodeJS and MongoDB as a backend service.I want to fetch data from server and store data in ro

相关标签:
2条回答
  • 2021-01-03 08:14

    Room Basics

    The Room library acts as an abstract layer for underlying SQLite database. Thus, Room annotations are used:

    1. To Database and Entities where entities are POJO classes representing table structures.
    2. To specify operation for retrieval, updation and deletion.
    3. To add constraints, such as foreign keys.
    4. Support for LiveData.

    There are 3 major components in Room

    1. Entity : A class annotated with the @Entity annotation is mapped to a table in database. Every entity is persisted in its own table and every field in class represents the column name.

      tableName attribute is used to define the name of the table Every entity class must have at-least one Primary Key field, annotated with @PrimaryKey Fields in entity class can be annotated with @ColumnInfo(name = “name_of_column”) annotation to give specific column names

    2. DAO : Data Access Object is either be an interface or an abstract class annotated with @Doa annotation, containing all the methods to define the operations to be performed on data. The methods can be annotated with

    @Query to retrieve data from database

    @Insert to insert data into database

    @Delete to delete data from database

    @Update to update data in database

    1. Database : Database is a container for tables. An abstract class annotated with @Database annotation is used to create a database with given name along with database version.

    Add these dependencies :

        dependencies {
        // Room dependencies
          compile 'android.arch.persistence.room:runtime:1.0.0'
          annotationProcessor 'android.arch.persistence.room:compiler:1.0.0'
        }
    

    Create Entity

    Before creating a database, Let's create an Entity, named as Note and later, Objects of this class will be added to database.

        @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 + '\'' +
                    '}';
        }}
    

    Creating DAOs

    DAOs define all methods to access database, annotated with @Dao annotation. The DAO acts as a contract to perform CRUD operations on data within a database.

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

    Create Database

    Now, we have table defined as Entity and CRUD methods defined via NoteDao. The last piece of the database puzzle is the database itself.

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

    Implement Database Interactions

    The below snippet will demonstrate the working of insert, update, and delete functionality using the Room database.

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

    Retrieve And Display NoteList

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

    Update Note

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

    Delete Note

    noteDatabase.getNoteDao().deleteNote(notes.get(pos));
    adapterObj.notifyDataSetChanged();
    
    0 讨论(0)
  • Android developers has a good start tutorial for Room: https://developer.android.com/training/data-storage/room/index.html

    For the functionallity you want to add would be good for you to use Repository Pattern. To keep it simple, the Repository Pattern is like a class between the app and the server where you ask some data (for example user name) and the app doesn't know where that data is coming from (database or server). The repository the will do something like this:

    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()
      }
    }
    

    This allows the app to decouple, and if you for example want to change server in a future, you would only have to change repository classes and the rest of the app will be the same. I recommend you to investigate it. You also should use an interface that the repository sould implement, this decouple a bit more

    0 讨论(0)
提交回复
热议问题