GreenDao与ReactiveX的完美搭配

BAT 批处理程序 2017-04-16

作为Android开发者,一定不会对 GreenDao 和 ReactiveX 陌生。

GreenDao   号称Android最快的关系型数据库

GreenDao与ReactiveX的完美搭配

ReactiveX    Rx是一个编程模型,目标是提供一致的编程接口,帮助开发者更方便的处理异步数据流。

GreenDao与ReactiveX的完美搭配

下面我们就通过一个实例,来讲解有无Rx支持的时候GreenDao应该怎么用,实现增删操作。

GreenDao与ReactiveX的完美搭配

首先导入需要的库(本文针对的 GreenDao 是 3.x 版本, Rx 是 1.x 版本)

GreenDao导入需求库的说明: https://github.com/greenrobot/greenDAO/

在 build.gradle(Project:Xxx) 下,添加:

buildscript {
    repositories {
        ...
        mavenCentral()
        ...
    }
    dependencies {
        ...
        classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2'
        ...
    }
}

在 build.gradle(Module:Xxx) 下,添加:

...
apply plugin: 'org.greenrobot.greendao'
...
dependencies {
    ...
    compile 'org.greenrobot:greendao:3.2.2'
    ...
}

Rx导入需求库的说明: https://github.com/ReactiveX/RxJava/tree/1.x

在 build.gradle(Module:Xxx) 下,添加:

dependencies {
    ...
    compile 'io.reactivex:rxjava:1.2.9'
    compile 'io.reactivex:rxandroid:1.2.1'
    ...
}

需求库添加完之后就可以进入正题了

1.参考GreenDao官方文档,添加必要的类 Note 、 NotesAdapter 、 NoteType 、 NoteTypeConverter

Note :

/**
 * Entity mapped to table "NOTE".
 */
@Entity(indexes = {
        @Index(value = "text, date DESC", unique = true)
})
public class Note {

    @Id
    private Long id;

    @NotNull
    private String text;
    private String comment;
    private java.util.Date date;

    @Convert(converter = NoteTypeConverter.class, columnType = String.class)
    private NoteType type;

    @Generated(hash = 1272611929)
    public Note() {
    }

    public Note(Long id) {
        this.id = id;
    }

    @Generated(hash = 1686394253)
    public Note(Long id, @NotNull String text, String comment, java.util.Date date, NoteType type) {
        this.id = id;
        this.text = text;
        this.comment = comment;
        this.date = date;
        this.type = type;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @NotNull
    public String getText() {
        return text;
    }

    /**
     * Not-null value; ensure this value is available before it is saved to the database.
     */
    public void setText(@NotNull String text) {
        this.text = text;
    }

    public String getComment() {
        return comment;
    }

    public void setComment(String comment) {
        this.comment = comment;
    }

    public java.util.Date getDate() {
        return date;
    }

    public void setDate(java.util.Date date) {
        this.date = date;
    }

    public NoteType getType() {
        return type;
    }

    public void setType(NoteType type) {
        this.type = type;
    }

}

NotesAdapter :

public class NotesAdapter extends RecyclerView.Adapter<NotesAdapter.NoteViewHolder> {

    private NoteClickListener clickListener;
    private List<Note> dataset;

    public interface NoteClickListener {
        void onNoteClick(int position);
    }

    static class NoteViewHolder extends RecyclerView.ViewHolder {

        public TextView text;
        public TextView comment;

        public NoteViewHolder(View itemView, final NoteClickListener clickListener) {
            super(itemView);
            text = (TextView) itemView.findViewById(R.id.textViewNoteText);
            comment = (TextView) itemView.findViewById(R.id.textViewNoteComment);
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (clickListener != null) {
                        clickListener.onNoteClick(getAdapterPosition());
                    }
                }
            });
        }
    }

    public NotesAdapter(NoteClickListener clickListener) {
        this.clickListener = clickListener;
        this.dataset = new ArrayList<Note>();
    }

    public void setNotes(@NonNull List<Note> notes) {
        dataset = notes;
        notifyDataSetChanged();
    }

    public Note getNote(int position) {
        return dataset.get(position);
    }

    @Override
    public NotesAdapter.NoteViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.item_note, parent, false);
        return new NoteViewHolder(view, clickListener);
    }

    @Override
    public void onBindViewHolder(NotesAdapter.NoteViewHolder holder, int position) {
        Note note = dataset.get(position);
        holder.text.setText(note.getText());
        holder.comment.setText(note.getComment());
    }

    @Override
    public int getItemCount() {
        return dataset.size();
    }
}

NoteType :

public enum NoteType {
    TEXT, LIST, PICTURE
}

NoteTypeConverter :

public class NoteTypeConverter implements PropertyConverter<NoteType, String> {
    @Override
    public NoteType convertToEntityProperty(String databaseValue) {
        return NoteType.valueOf(databaseValue);
    }

    @Override
    public String convertToDatabaseValue(NoteType entityProperty) {
        return entityProperty.name();
    }
}

必要的类添加之后,接下来就是重头戏:

用代码说话,横向比较 GreenDao 在有无 Rx 的支持下应该如何书写

1.初始化类

无 Rx 写法                                                

private NoteDao noteDao;
private Query<Note> notesQuery;

 有 Rx 写法

private RxDao<Note, Long> noteDao;
private RxQuery<Note> notesQuery;

2.将记录保存到DAO里

无 Rx 写法 

DaoSession daoSession = ((BaseApplication) getApplication()).getDaoSession();
noteDao = daoSession.getNoteDao();

有 Rx 写法

DaoSession daoSession = ((BaseApplication) getApplication()).getDaoSession();
noteDao = daoSession.getNoteDao().rx();

3.查询所有记录,按A-Z分类

无 Rx 写法

notesQuery = noteDao.queryBuilder().orderAsc(NoteDao.Properties.Text).build();

有 Rx 写法

notesQuery = daoSession.getNoteDao().queryBuilder().orderAsc(NoteDao.Properties.Text).rx();

4.初始化View

无 Rx 写法

protected void setUpViews() {
        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerViewNotes);
        //noinspection ConstantConditions
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));

        notesAdapter = new NotesAdapter(noteClickListener);
        recyclerView.setAdapter(notesAdapter);

        addNoteButton = findViewById(R.id.buttonAdd);
        //noinspection ConstantConditions
        addNoteButton.setEnabled(false);

        editText = (EditText) findViewById(R.id.editTextNote);
        editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {

            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                if (actionId == EditorInfo.IME_ACTION_DONE) {
                    addNote();
                    return true;
                }
                return false;
            }
        });
        editText.addTextChangedListener(new TextWatcher() {

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                boolean enable = s.length() != 0;
                addNoteButton.setEnabled(enable);
            }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }

            @Override
            public void afterTextChanged(Editable s) {
            }
        });
    }

有 Rx 写法

protected void setUpViews() {
        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerViewNotes);
        //noinspection ConstantConditions
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));

        notesAdapter = new NotesAdapter(noteClickListener);
        recyclerView.setAdapter(notesAdapter);

        addNoteButton = findViewById(R.id.buttonAdd);

        editText = (EditText) findViewById(R.id.editTextNote);
        //noinspection ConstantConditions
        RxTextView.editorActions(editText).observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1<Integer>() {
                    @Override
                    public void call(Integer actionId) {
                        if (actionId == EditorInfo.IME_ACTION_DONE) {
                            addNote();
                        }
                    }
                });
        RxTextView.afterTextChangeEvents(editText).observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1<TextViewAfterTextChangeEvent>() {
                    @Override
                    public void call(TextViewAfterTextChangeEvent textViewAfterTextChangeEvent) {
                        boolean enable = textViewAfterTextChangeEvent.editable().length() > 0;
                        addNoteButton.setEnabled(enable);
                    }
                });
    }

5.更新记录

无 Rx 写法

private void updateNotes() {
    List<Note> notes = notesQuery.list();
    notesAdapter.setNotes(notes);
}

有 Rx 写法

private void updateNotes() {
    notesQuery.list()
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Action1<List<Note>>() {
                @Override
                public void call(List<Note> notes) {
                    notesAdapter.setNotes(notes);
                }
            });
}

6.添加记录

无 Rx 写法

private void addNote() {
        String noteText = editText.getText().toString();
        editText.setText("");

        final DateFormat df = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM);
        String comment = "Added on " + df.format(new Date());

        Note note = new Note();
        note.setText(noteText);
        note.setComment(comment);
        note.setDate(new Date());
        note.setType(NoteType.TEXT);
        noteDao.insert(note);
        Log.d("DaoExample", "Inserted new note, ID: " + note.getId());

        updateNotes();
    }

有 Rx 写法

private void addNote() {
        String noteText = editText.getText().toString();
        editText.setText("");

        final DateFormat df = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM);
        String comment = "Added on " + df.format(new Date());

        Note note = new Note(null, noteText, comment, new Date(), NoteType.TEXT);
        noteDao.insert(note)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1<Note>() {
                    @Override
                    public void call(Note note) {
                        Log.d("DaoExample", "Inserted new note, ID: " + note.getId());
                        updateNotes();
                    }
                });
    }

7.删除记录

无 Rx 写法

NotesAdapter.NoteClickListener noteClickListener = new NotesAdapter.NoteClickListener() {
        @Override
        public void onNoteClick(int position) {
            Note note = notesAdapter.getNote(position);
            Long noteId = note.getId();

            noteDao.deleteByKey(noteId);
            Log.d("DaoExample", "Deleted note, ID: " + noteId);

            updateNotes();
        }
    };

有 Rx 写法

NotesAdapter.NoteClickListener noteClickListener = new NotesAdapter.NoteClickListener() {
        @Override
        public void onNoteClick(int position) {
            Note note = notesAdapter.getNote(position);
            final Long noteId = note.getId();

            noteDao.deleteByKey(noteId)
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Action1<Void>() {
                        @Override
                        public void call(Void aVoid) {
                            Log.d("DaoExample", "Deleted note, ID: " + noteId);
                            updateNotes();
                        }
                    });
        }
    };

最后别忘了新建一个Application类,并添加到Manifest中

public class BaseApplication extends Application {

    /**
     * A flag to show how easily you can switch from standard SQLite to the encrypted SQLCipher.
     */
    public static final boolean ENCRYPTED = true;

    private DaoSession daoSession;

    @Override
    public void onCreate() {
        super.onCreate();

        DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(                this, ENCRYPTED ? "notes-db-encrypted" : "notes-db");
        Database db = ENCRYPTED ? helper.getEncryptedWritableDb("super-secret") : helper.getWritableDb();
        daoSession = new DaoMaster(db).newSession();
    }

    public DaoSession getDaoSession() {
        return daoSession;
    }

}

文中额外可能会用到的库

compile 'com.jakewharton.rxbinding:rxbinding:1.0.1'
compile 'net.zetetic:android-database-sqlcipher:3.5.6'

关注我的新浪微博,获取更多Android开发资讯!关注科技评论家,领略科技、创新、教育以及最大化人类智慧与想象力!

相关推荐