美文网首页
任务 6.2 云笔记 - 云端存储数据(3)

任务 6.2 云笔记 - 云端存储数据(3)

作者: jingz课程 | 来源:发表于2018-05-21 21:56 被阅读0次

三、实现ServerNoteRepository

ServerNoteRepository作为新的数据仓库实现类,它通过访问服务端的各个操作接口来实现数据的提交和获取。我们仍然使用okhttp3开源框架来完成这些基于HTTP协议的网络操作。


3.1 修改HttpHelper类

首先打开帮助类HttpHelper,向里面添加相关的常量和URL获取方法。
增加如下的常量定义:

    private static final String NOTE_URL = HTTP_PREFIX + "note.php";
    private static final String SAVE_NOTE_URL = NOTE_URL + "?p=save";
    private static final String FIND_NOTE_URL = NOTE_URL + "?p=find&id=";
    private static final String FIND_ALL_NOTE_URL = NOTE_URL + "?p=findall";

    private static final String NOTEBOOK_URL = HTTP_PREFIX + "notebook.php";
    private static final String SAVE_NOTEBOOK_URL = NOTEBOOK_URL + "?p=save";
    private static final String FIND_NOTEBOOK_URL = NOTEBOOK_URL + "?p=find&id=";
    private static final String FIND_ALL_NOTEBOOK_URL = NOTEBOOK_URL + "?p=findall";

增加如下的方法:

    // 获取保存笔记页面地址
    public static String getSaveNoteUrl() {
        return SAVE_NOTE_URL;
    }
    // 获取根据id查找笔记页面地址
    public static String getFindNoteUrl(long id) {
        return FIND_NOTE_URL + id;
    }
    // 获取查找全部笔记页面地址
    public static String getFindAllNoteUrl() {
        return FIND_ALL_NOTE_URL;
    }

    // 获取保存笔记本页面地址
    public static String getSaveNotebookUrl() {
        return SAVE_NOTEBOOK_URL;
    }
    // 获取根据id查找笔记本页面地址
    public static String getFindNotebookUrl(long id) {
        return FIND_NOTEBOOK_URL + id;
    }
    // 获取查找全部笔记本页面地址
    public static String getFindAllNotebookUrl() {
        return FIND_ALL_NOTEBOOK_URL;
    }

3.2 完成ServerNoteRepository类

3.2.1 增加构造方法以获取Context对象

为ServerNoteRepository类增加Context类型的成员,并为其创建构造方法,从外界接收一个Context对象进行初始化:

    private Context context;
    public ServerNoteRepository(Context context) {
        this.context = context;
    }

3.2.2 构造单例模式

仍然按照基于本地数据库的NoteRepository的方式构造成单例。向ServerNoteRepository类中添加如下代码:

    private static ServerNoteRepository sInstance;

    //获取单例对象
    public static ServerNoteRepository getInstance(Context context) {
        if (sInstance == null) {
            sInstance = new ServerNoteRepository(context);
        }
        return sInstance;
    }

3.2.3 getAllNotes()

这里应当访问对应的获取全部笔记记录的接口,并提供当前email账号。对返回的结果(JSON)进行解析,得到笔记对象列表。在编写代码如下:

    @Override
    public ArrayList<Note> getAllNotes() {
        ArrayList<Note> notes = new ArrayList<>();

        String email = Utils.getUserEmail(context);
        // 当前并没有登录
        if (TextUtils.isEmpty(email)) {
            return notes;
        }

        OkHttpClient client = new OkHttpClient();
        // 创建包含email账号的表单,
        FormBody.Builder fb = new FormBody.Builder();
        FormBody formBody = fb.add("email", email)
                .build();
        // 创建获取全部笔记的请求
        Request request = new Request.Builder()
                .url(HttpHelper.getFindAllNoteUrl())
                .post(formBody)
                .build();
        Call call = client.newCall(request);
        try {
            // 执行请求并返回结果
            Response response = call.execute();
            if (response != null) {
                String json = response.body().string();
                if (!TextUtils.isEmpty(json)) {
                    JSONObject jo = new JSONObject(json);
                    int code = jo.optInt("code", 0);
                    if (code == 1) {
                        JSONArray array = jo.optJSONArray("noteList");
                        // 逐个解析出获取到的笔记,并插入列表
                        for (int i = 0; i < array.length(); i++) {
                            JSONObject jnote = array.getJSONObject(i);
                            long id = jnote.optLong("id");
                            String title = jnote.optString("title");
                            String content = jnote.optString("content");
                            long createTime = jnote.optLong("createTime");
                            long notebookId = jnote.optLong("notebookId");
                            Note note = new Note(id, title, content, createTime, notebookId);
                            notes.add(note);
                        }
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return notes;
    }

3.2.4 saveNote()

在这里,要将参数传来的Note对象信息提交到服务器端并存储。成功后将返回新存储的笔记的id。将此id设置给被保存的note对象并作为方法返回值。
编写代码如下:

    @Override
    public Note saveNote(Note note) {
        String email = Utils.getUserEmail(context);
        if (note == null || TextUtils.isEmpty(email)) {
            return note;
        }

        OkHttpClient client = new OkHttpClient();
        // 创建包含被保存笔记信息和email账号的表单,
        FormBody.Builder fb = new FormBody.Builder();
        FormBody formBody = fb.add("email", email)
                .add("title", note.getTitle())
                .add("content", note.getContent())
                .add("createTime", String.valueOf(note.getCreateTime()))
                .add("notebookId", String.valueOf(note.getNotebookId()))
                .build();
        // 创建保存笔记的请求
        Request request = new Request.Builder()
                .url(HttpHelper.getSaveNoteUrl())
                .post(formBody)
                .build();
        Call call = client.newCall(request);

        try {
            Response response = call.execute();
            if (response != null) {
                String json = response.body().string();
                if (!TextUtils.isEmpty(json)) {
                    JSONObject jo = new JSONObject(json);
                    int code = jo.optInt("code", 0);
                    if (code == 1) {    // 提交成功
                        long id = jo.optLong("id");
                        if (id <= 0) {
                            return null;
                        }
                        note.setId(id);
                    } else {    // 保存失败,返回null
                        return null;
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        }

        return note;
    }

3.2.4 getNote()

这里根据参数指定的笔记id提交服务器查询,在根据返回的数据生成笔记对象。编写代码如下:

    @Override
    public Note getNote(long noteId) {
        // 检查登录状态及参数合法性
        String email = Utils.getUserEmail(context);
        if (noteId <= 0 || TextUtils.isEmpty(email)) {
            return null;
        }

        OkHttpClient client = new OkHttpClient();
        // 创建包含email账号的表单,
        FormBody.Builder fb = new FormBody.Builder();
        FormBody formBody = fb.add("email", email)
                .build();
        // 创建查找笔记的请求
        Request request = new Request.Builder()
                .url(HttpHelper.getFindNoteUrl(noteId))
                .post(formBody)
                .build();
        Call call = client.newCall(request);

        try {
            Response response = call.execute();
            if (response != null) {
                String json = response.body().string();
                if (!TextUtils.isEmpty(json)) {
                    JSONObject jo = new JSONObject(json);
                    int code = jo.optInt("code", 0);
                    if (code == 1) {    // 提交成功
                        JSONObject jnote = jo.optJSONObject("note");
                        long id = jnote.optLong("id");
                        String title = jnote.optString("title");
                        String content = jnote.optString("content");
                        long createTime = jnote.optLong("createTime");
                        long notebookId = jnote.optLong("notebookId");
                        return new Note(id, title, content, createTime, notebookId);
                    } else {    // 保存失败,返回null
                        return null;
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        }


        return null;
    }

3.2.5 saveNotebook()

向服务器提交并保存参数给出的笔记本对象。与保存笔记对象思路基本一致。编写代码如下:

    @Override
    public Notebook saveNotebook(Notebook notebook) {
        String email = Utils.getUserEmail(context);
        if (notebook == null || TextUtils.isEmpty(email)) {
            return notebook;
        }

        OkHttpClient client = new OkHttpClient();
        // 创建包含被保存笔记本信息和email账号的表单,
        FormBody.Builder fb = new FormBody.Builder();
        FormBody formBody = fb.add("email", email)
                .add("name", notebook.getName())
                .build();
        // 创建保存笔记本的请求
        Request request = new Request.Builder()
                .url(HttpHelper.getSaveNotebookUrl())
                .post(formBody)
                .build();
        Call call = client.newCall(request);

        try {
            Response response = call.execute();
            if (response != null) {
                String json = response.body().string();
                if (!TextUtils.isEmpty(json)) {
                    JSONObject jo = new JSONObject(json);
                    int code = jo.optInt("code", 0);
                    if (code == 1) {    // 提交成功
                        long id = jo.optLong("id");
                        if (id <= 0) {
                            return null;
                        }
                        notebook.setId(id);
                    } else {    // 保存失败,返回null
                        return null;
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        }

        return notebook;
    }

3.2.6 getAllNotebooks()

编写代码如下:

    @Override
    public ArrayList<Notebook> getAllNotebooks() {
        ArrayList<Notebook> notebooks = new ArrayList<>();

        String email = Utils.getUserEmail(context);
        // 当前并没有登录
        if (TextUtils.isEmpty(email)) {
            return notebooks;
        }

        OkHttpClient client = new OkHttpClient();
        // 创建包含email账号的表单,
        FormBody.Builder fb = new FormBody.Builder();
        FormBody formBody = fb.add("email", email)
                .build();
        // 创建获取全部笔记本的请求
        Request request = new Request.Builder()
                .url(HttpHelper.getFindAllNotebookUrl())
                .post(formBody)
                .build();
        Call call = client.newCall(request);
        try {
            // 执行请求并返回结果
            Response response = call.execute();
            if (response != null) {
                String json = response.body().string();
                if (!TextUtils.isEmpty(json)) {
                    JSONObject jo = new JSONObject(json);
                    int code = jo.optInt("code", 0);
                    if (code == 1) {
                        JSONArray array = jo.optJSONArray("notebookList");
                        // 逐个解析出获取到的笔记本,并插入列表
                        for (int i = 0; i < array.length(); i++) {
                            JSONObject jnote = array.getJSONObject(i);
                            long id = jnote.optLong("id");
                            String name = jnote.optString("name");
                            Notebook nb = new Notebook(id, name);
                            notebooks.add(nb);
                        }
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return notebooks;
    }

3.2.7 getNotebook()

这里同样根据给出的id获取笔记本,实际上我们目前没有用到这个方法。为了使架构完备,还是补齐它的实现:

    @Override
    public Notebook getNotebook(long notebookId) {
        // 检查登录状态及参数合法性
        String email = Utils.getUserEmail(context);
        if (notebookId <= 0 || TextUtils.isEmpty(email)) {
            return null;
        }

        OkHttpClient client = new OkHttpClient();
        // 创建包含email账号的表单,
        FormBody.Builder fb = new FormBody.Builder();
        FormBody formBody = fb.add("email", email)
                .build();
        // 创建查找笔记的请求
        Request request = new Request.Builder()
                .url(HttpHelper.getFindNotebookUrl(notebookId))
                .post(formBody)
                .build();
        Call call = client.newCall(request);

        try {
            Response response = call.execute();
            if (response != null) {
                String json = response.body().string();
                if (!TextUtils.isEmpty(json)) {
                    JSONObject jo = new JSONObject(json);
                    int code = jo.optInt("code", 0);
                    if (code == 1) {    // 提交成功
                        JSONObject jnote = jo.optJSONObject("note");
                        long id = jnote.optLong("id");
                        String name = jnote.optString("name");
                        return new Notebook(id, name);
                    } else {    // 保存失败,返回null
                        return null;
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        }


        return null;
    }

3.2.8 修改对笔记本数据访问的调用

在任务6.1中实现的笔记本功能相对比较草率,忽略了对耗时操作的处理。我们来进行修正。
打开NotebooksActivity类。找到其中的onNewNotebook()方法,按如下的方式改写这个方法:

    public void onNewNotebook(View view) {
        // 创建编辑框对象
        final EditText notebookNameEdit = new EditText(this);
        AlertDialog.Builder builder = new AlertDialog.Builder(this)
                .setTitle(R.string.new_notebook)
                .setView(notebookNameEdit)  // 将编辑框对象加入对话框
                .setNegativeButton("取消", null)
                .setPositiveButton("确认", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        final String name = notebookNameEdit.getEditableText().toString();
                        if (!TextUtils.isEmpty(name)) {
                            // 异步方式处理笔记本数据提交
                            AsyncTask<Void, Void, Notebook> task = new AsyncTask<Void, Void, Notebook>() {
                                @Override
                                protected Notebook doInBackground(Void... voids) {
                                    Notebook nb = new Notebook(0, name);
                                    nb = NoteRepositoryFactory.getNoteRepository(getApplicationContext()).saveNotebook(nb);
                                    return nb;
                                }

                                @Override
                                protected void onPostExecute(Notebook notebook) {
                                    if (notebook != null) {
                                        // 插入成功,刷新笔记本列表
                                        asyncLoadNotebooks();
                                    } else {
                                        // 插入失败,提示用户
                                        Toast.makeText(NotebooksActivity.this, "保存笔记本失败", Toast.LENGTH_SHORT).show();
                                    }
                                }
                            };
                            task.execute();
                        }
                    }
                });
        builder.show();
    }

同时找到以下代码:

ArrayList<Notebook> nbs = NoteDAO.getInstance(NotebooksActivity.this.getApplicationContext()).queryAllNotebooks();

将其替换为:

ArrayList<Notebook> nbs = NoteRepositoryFactory.getNoteRepository(getApplicationContext()).getAllNotebooks();

3.2.9 在NoteRepositoryFactory中增加对ServerNoteRepository的支持

打开工厂类NoteRepositoryFactory,按如下代码改写getNoteRepository()方法:

    public static INoteRepository getNoteRepository(Context context) {
        switch (BuildConfig.USE_TEST_REPO) {
            case "test":
                return TestNoteRepository.getInstance();
            case "database":
                return NoteRepository.getInstance(context);
            case "server":
                return ServerNoteRepository.getInstance(context);
        }
        return null;
    }

3.2.10 修改build.gradle脚本

打开build.gradle文件,找到如下的区域:

    buildTypes {
     ...   
    }

改写为如下形式:

    buildTypes {

        debug {
            buildConfigField "String", "USE_TEST_REPO", '"server"'
        }

        release {
            buildConfigField "String", "USE_TEST_REPO", '"server"'
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }

        repoTest {
            buildConfigField "String", "USE_TEST_REPO", '"test"'
        }
    }

到此为止,基本的服务器端数据存储访问就完成了,可以运行程序体验效果。

相关文章

网友评论

      本文标题:任务 6.2 云笔记 - 云端存储数据(3)

      本文链接:https://www.haomeiwen.com/subject/ltpfjftx.html