一、新的数据仓库ServerNoteRepository
目前我们的笔记以及笔记本数据均存储在手机端应用程序私有的数据库中。这种方式存在以下的弊端:
- 应用程序删除或遭到意外破坏后则数据丢失
- 其它设备(手机、平板、桌面电脑等)无法共用数据
因此,从安全性和便利性来考虑,将数据存储到服务器端更为合理。
1.1 回顾
在我们项目的架构中,用数据仓库接口INoteRepository定义了数据操作的集合,然后给出了两种实现类:
- 第一种是用于验证UI功能的基于内存数据的TestNoteRepository类
- 第二种是基于本地数据库存储SQLite的NoteRepository类
随后我们通过build.gradle文件中的Gradle脚本来配置采用何种实现:
buildTypes {
debug {
buildConfigField "String", "USE_TEST_REPO", '"database"'
}
release {
buildConfigField "String", "USE_TEST_REPO", '"database"'
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
repoTest {
buildConfigField "String", "USE_TEST_REPO", '"test"'
}
}
1.2 扩展INoteRepository接口
我们在任务6.1增加笔记本功能的时候,直接通过NoteDAO类来访问数据。这样做其实是违背我们最初的架构设计的。我们在这里进行扩展INoteRepository接口,增加对笔记本数据的操作。
回顾任务6.1中我们在NoteDAO类中针对笔记本数据定义的几个方法:
- insertNotebook():插入笔记本数据
- queryAllNotebooks():查询全部笔记本记录
- queryNotebookById():根据笔记本id查询对应的笔记本数据
那么,我们改写INoteRepository接口,增加相应的操作。扩展后的接口代码如下:
public interface INoteRepository {
// 笔记数据相关操作
ArrayList<Note> getAllNotes();
Note saveNote(Note note);
Note getNote(long noteId);
// 扩展:笔记本数据相关操作
Notebook saveNotebook(Notebook notebook);
ArrayList<Notebook> getAllNotebooks();
Notebook getNotebook(long notebookId);
}
这次改动必然会导致已有的INoteRepository接口的两个实现类报错:它们并没有实现新增的方法。
在这里,我们不在已有的实现类中一一增补新方法的实现。因为存在一种可能——某个实现类只关心接口中的一部分方法。这种情况下,这个实现类必须实现那些接口中必须实现而自己又不会被调用的操作。
我们采取另一种思路:提供一个接口的基础实现类BaseNoteRepository。BaseNoteRepository类提供INoteRepository接口的缺省实现。接下来,改写原来的实现类——由直接实现(implements)INoteRepository接口,改为扩展(extends)BaseNoteRepository。这样,INoteRepository扩展导致的错误就消失了。
在repository包中创建新类BaseNoteRepository,使其实现接口INoteRepository:
完成创建后打开BaseNoteRepository.java文件。里面不出意外地会报告错误。自动产生全部需要实现的方法如下:
public class BaseNoteRepository implements INoteRepository {
@Override
public ArrayList<Note> getAllNotes() {
return null;
}
@Override
public Note saveNote(Note note) {
return null;
}
@Override
public Note getNote(long noteId) {
return null;
}
@Override
public Notebook saveNotebook(Notebook notebook) {
return null;
}
@Override
public ArrayList<Notebook> getAllNotebooks() {
return null;
}
@Override
public Notebook getNotebook(long notebookId) {
return null;
}
}
这样,我们得到了一个缺省的实现。当然,这个实现没有实际的功能。分别修改两个实现类。
TestNoteRepository:
原来的类定义如下:
public class TestNoteRepository implements INoteRepository {
修改为:
public class TestNoteRepository extends BaseNoteRepository {
NoteRepository:
原来的类定义如下:
public class NoteRepository implements INoteRepository {
修改为:
public class NoteRepository extends BaseNoteRepository {
这样,错误提示消失。通过增加BaseNoteRepository类,以尽可能少的代价为旧代码提供了兼容性。
1.3 创建ServerNoteRepository类
新建ServerNoteRepository类来实现基于服务器端数据库的数据仓库。仍然在repository包中创建此类:
创建完成后,进入源代码,内容如下:
public class ServerNoteRepository extends BaseNoteRepository {
}
在这里,我们要重新实现所有INoteRepository接口中声明的方法。按Ctrl+O启动重写方法对话框,并同时选择列出的全部6个INoteRepository接口方法:
点击“OK”,开发环境自动生成这些方法的代码:
public class ServerNoteRepository extends BaseNoteRepository {
@Override
public ArrayList<Note> getAllNotes() {
return super.getAllNotes();
}
@Override
public Note saveNote(Note note) {
return super.saveNote(note);
}
@Override
public Note getNote(long noteId) {
return super.getNote(noteId);
}
@Override
public Notebook saveNotebook(Notebook notebook) {
return super.saveNotebook(notebook);
}
@Override
public ArrayList<Notebook> getAllNotebooks() {
return super.getAllNotebooks();
}
@Override
public Notebook getNotebook(long notebookId) {
return super.getNotebook(notebookId);
}
}
之后,我们将一一完成这些方法,使其通过服务器端提供的接口来访问服务器端数据。不过,目前我们还没有在服务器端为笔记和笔记本数据创建存储,也没有提供响应的访问接口。下面,我们的工作就转向服务器端。