Android项目实战开发-----期末总结2

项目三:网络层和数据模型的封装

任务一:网络请求和数据解析

1,网络请求

(1)Android中的网络存储主要是使用HTTP/HTTPS协议访问服务器,与服务器发生数据交互。

(2)Android提供两种执行HTTP请求的方式:

  • ​ HttpClient请求(有bugs,API23已经被弃用)​ HttpURLConnection请求

HttpUrlConnection执行http Get请求核心代码:

 public class PostUtils {
    public static String LOGIN_URL = "填URL地址";
​
    public static String LoginByPost(String number, String passwd) {
        String msg = "";
        try {
            HttpURLConnection conn = (HttpURLConnection) new URL(LOGIN_URL).openConnection();
            // 设置请求方式,请求超时信息
            conn.setRequestMethod("POST");
            conn.setReadTimeout(5000);
            conn.setConnectTimeout(5000);
            // 设置运行输入,输出:
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // Post方式不能缓存,需手动设置为false
            conn.setUseCaches(false);
            // 我们请求的数据:
            String data = "passwd=" + URLEncoder.encode(passwd, "UTF-8") + "&number=" + URLEncoder.encode(number, "UTF-8");
            // 这里可以写一些请求头的东东...
            // 获取输出流
            OutputStream out = conn.getOutputStream();
            out.write(data.getBytes());
            out.flush();
            if (conn.getResponseCode() == 200) {
                // 获取响应的输入流对象
                InputStream is = conn.getInputStream();
                // 创建字节输出流对象
                ByteArrayOutputStream message = new ByteArrayOutputStream();
                // 定义读取的长度
                int len = 0;
                // 定义缓冲区
                byte buffer[] = new byte[1024];
                // 按照缓冲区的大小,循环读取
                while ((len = is.read(buffer)) != -1) {
                    // 根据读取的长度写入到os对象中
                    message.write(buffer, 0, len);
                }
                // 释放资源
                is.close();
                message.close();
                // 返回字符串
                msg = new String(message.toByteArray());
                return msg;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return msg;
    }
}

(3)使用OKhttp框架进行网络请求(基于HttpURLConnection进行封装)

OKhttp可以实现的功能:

  • get/post同步,异步请求

  • HTTPS安全证书形式的网络请求

  • 文件上传和下载

  • 图片加载

  • 支持请求回调,直接返回对象或者对象的集合

  • 支持session的保存

OKhttp的特点:

  • Http/2支持多路复用

  • 采用连接池减少请求延时

  • 支持GZIP压缩

  • 相应缓存

  • 支持websocket

  • 多IP切换(连接失败并且服务器有多IP)

OKhttp的使用

使用OKhttp执行 GET请求的使用步骤

  • 第一步:新建一个OkhttpClient对象,这个对象最好在整个APP中只有一个实例存在。

  • 第二步:新建一个Request请求对象,它使用Builder的方式进行创建,需要包含请求的接口URL

  • 第三步:使用OkhttpClient对象新建一个Call请求,并传入Request对象

  • 第四步:将Call加入请求队列,执行该请求

示例核心代码:

   
 /**
     * OkHttp 异步 Get 请求
     */
    private void httpAsynchronousGet() {
        // Request 中封装了请求相关信息
        Request request = new Request.Builder()
                .url("https://www.baidu.com")   // 设置请求地址
                .get()                          // 使用 Get 方法
                .build();
​
        // 异步 Get 请求
        mOkHttpClient.newCall(request).enqueue(new Callback(){
​
            @Override
            public void onFailure(Call call, IOException e) {
                // 请求失败的情况
            }
​
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                // 请求成功 , 获取
                String result = response.body().string();
                Log.i(TAG, "result : " + result);
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        // 主线程中执行相关代码
                    }
                });
            }
        });
    }

使用Okhttp执行Http POST请求的使用步骤

  • 第一步:新建一个OkhttpClient对象。

  • 第二步:使用FormBody来构建包含键值对类型参数的请求体。

  • 第三步:新建一个Request请求对象,需要包含请求的接口URL和请求体

  • 第四步:使用OkhttpClient对象新建一个Call请求,并传入Request对象

  • 第五步:将Call加入请求队列,执行该请求

示例核心代码:

    /**
     * OkHttp 异步 Post 请求
     */
    private void httpAsynchronousPost() {
        // 创建 Post 表单 , 主要用于设置 Post 请求键值对
        FormBody formBody = new FormBody.Builder()
                .add("Key", "Value")
                .build();
​
        // Request 中封装了请求相关信息
        Request request = new Request.Builder()
                .url("https://www.baidu.com")   // 设置请求地址
                .post(formBody)                 // 使用 Post 方法
                .build();
​
        // 创建异步回调
        Callback callback = new Callback(){
​
            @Override
            public void onFailure(Call call, IOException e) {
                // 请求失败的情况
            }
​
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                // 请求成功 , 获取
                String result = response.body().string();
                Log.i(TAG, "result : " + result);
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        // 主线程中执行相关代码
                    }
                });
            }
        };
        // 异步 Get 请求
        mOkHttpClient.newCall(request).enqueue(callback);
    }

2,数据解析

(1)概述

  • 我们与服务器进行数据交互的数据格式大部分都是JSON格式(取代XML的数据结构)

  • 对JSON数据进行反序列化操作,转换成相应的对象或集合-------数据解析

  • JSON的语法(JSON本质是一种特定的字符串):“[ ]”表示数组,“{ }”表示对象,数据以键值对的进行表示。

  • JSON解析的结果有两种形式:一种是Javabean(单个对象实体类的对象);另一种是集合。它可以是List,List

(2)传统的数据解析(根据JSON字符串不同,解析的方式也不同)

Android项目实战开发-----期末总结2_第1张图片

常见的是JSONObject(对应一个实体类的对象)和JSONArray(对应一个数组)互相嵌套使用

(3)Gson框架解析

主要提供两个方法:

​ fromJson()方法--------实现将JSON数据转换为相应的Java对象。

核心代码示例:

​
    Gson gson = new Gson();
    String personTest = gson.toJson(p);
​

​ toJson()方法-----------实现将Java对象转换为相对应的JSON数据。

​
Person person = gson.fromJson(personTest, Person.class);
System.out.println(person);

Gson框架的优点:

​ 实现Java对象和JSON之间的互相转换。

​ 允许已经存在的无法改变的对象,转换成JSON,或者JSON转换成已存在的对象。

​ 允许自定义对象的表现形式。

​ 支持任意的复杂对象。

​ 能够生成可压缩和可读的JSON的字符串输出。

Gson框架使用关键:

​ 推荐把成员变量都声明成private修饰。

​ 如果某个字段被transient关键词修饰,就不会被序列化或者反序列化。

​ 当序列化的时候,如果对象的某个字段为null,是不会输出到JSON字符串中的。

​ 当反序列化的时候,某个字段在JSON字符串中找不到对应的值,就会被赋值为null。

​ 当内部类的某个字段和外部类的某个字段一样的话,就会被忽视,不会被序列化或者反序列化。

Gson框架的使用示例:(略)

任务二:数据模型的封装

1,理解MVP架构模式

MVP是传统MVC架构模式的扩展。使用MVC架构模式,开发者常会遇到以下困难:

  • 大部分的核心业务逻辑放在Controller中,在应用程序的整个生命周期内,这个文件会变得越来越大,越来越难维护。

  • 由于UI和业务逻辑的紧密耦合,Controller层和View层都将属于同一个activity或fragment。这将导致在更改应用程序功能时出现问题。

  • 由于大多数测试的部分依赖Android SDK组件,因此针对不同层执行单元测试时变得困难了。

MVP模式克服了MVC模式的这些挑战,并且提供了一种简单的方法来构造项目代码。MVP模式之所以被广泛接受,因为它提供了模块化、可测试以及更干净和更易于维护的代码基准。它由以下三部分组成:

  • Model:用于存储数据。它负责处理领域逻辑以及与数据库或网络层的通信。

  • View:UI层,提供数据可视化界面,并跟踪用户的操作,以便通知presenter。

  • Presenter:从Model层获取数据,并且应用UI逻辑来决定显示什么。它管理View的状态,并且根据来自于View的用户的输入执行动作。

Android项目实战开发-----期末总结2_第2张图片

mvp架构要点

  1. View和Presenter以及Presenter和Model之间通过接口(也称为contract)通信。

  2. 一个Presenter管理一个View,即:presenter和view是一对一的关系。

  3. Model和View之间无关联。

2,数据模型的封装(略)

3,引入greenDao数据库框架

(1)用于生成数据库代码

任务三:网络框架的封装

1,Retrofit概述(Retrofit将您的HTTP API转换为Java接口;Retrofit 是一个 RESTful 的 HTTP网络请求框架的封装,网络请求的工作本质上是 OkHttp 完成,而 Retrofit 仅负责网络请求接口的封装;)

(1)Square公司非常严格的RestFul客户端库,采用注解来描述HTTP请求,默认会集成URL参数替换。

(2)提供了自定义头信息,多请求体,文件上传下载,模拟响应等

(3)基本包含Okhttp库的所以特性和功能。

(4)引入

(5)使用说明

1,引用,在gradle文件中引用retrofit2、定义接口,Retrofit要求定义一个网络请求的接口,接口函数里要定义url路径、请求参数、返回类型。3、依次获得Retrofit对象、接口实例对象、网络工作对象 首先,需要新建一个retrofit对象。

​ 然后,根据上一步的接口,实现一个retrofit加工过的接口对象。

​ 最后,调用接口函数,得到一个可以执行网络访问的网络工作对象。

4、访问网络数据,用上一步获取的worker对象,执行网络请求,在回调函数里,取得我们需要的BizEntity数据对象。网络访问结束。

2,RxJava

(1)概述

​ 1)是一个在Java VM上使用可观测的序列化来组成异步的,基于事件的程序的库。

​ 2)质就是一个实现异步操作的库,异步操作的实现通过一种可扩展的观察者模式。

​ 3)RxJava的观察者模式主要有四个概念:

  • 被观察者:Observable,相当于Button。

  • 观察者:Observer,相当于onClickListener

  • 订阅:subscribe,相当于setOnClickListener。

  • 事件:普通事件onNext(),相当于onClick;

    4)它还有一些事件:onCompleted()/onError()/onStart()

2,引入()

1、引入 RxJava 依赖

Gradle 项目中 , 在 build.gradle 构建脚本中 , 添加如下依赖 ;

dependencies {
    implementation 'io.reactivex.rxjava2:rxjava:2.2.21'
}

rxjava3 依赖 :

dependencies {
    implementation 'io.reactivex.rxjava3:rxjava:3.0.0'
}
​

3,使用说明

1、定义 Observer 观察者

Observer(观察者): Observer 表示一个接收 Observable 发送消息 的观察者。 它可以处理从 Observable 发射的消息, 还可以处理错误和完成的事件。

Observer 观察者 是 操作的核心 , 定义在需要进行具体操作的位置 , 执行具体的 异步操作 或 事件 ;

如 : 在 UI 界面中 , 点击按钮 , 查询远程数据库服务器中的数据 , 查询完毕后更新 UI 界面 ;

该 Observer 观察者 就需要 定义在 UI 界面中 , 可以获取到相关的 UI 组件进行数据更新 ;Observable 被观察者可以定义在 Observer 观察者位置 , 也可以定义在消息发送的位置 , 这里 推荐定义在消息发送的位置 ;调用时 , 将 Observer 观察者 传递给对应的异步操作函数 ;在异步操作函数中 , 创建 Observable 被观察者 , 并且通过订阅将观察者订阅到被观察者中 ;订阅操作 , 就会同时发送消息给 观察者 ;

Observer 观察者定义代码 :

Observer observer = new Observer() {
    @Override
    public void onSubscribe(Disposable d) {
        // 当观察者订阅时的回调
    }
​
    @Override
    public void onNext(String value) {
        // 当接收到新的事件时的回调
        System.out.println(value);
    }
​
    @Override
    public void onError(Throwable e) {
        // 当发生错误时的回调
    }
​
    @Override
    public void onComplete() {
        // 当事件流结束时的回调
    }
};

2、定义 Observable 被观察者

Observable(被观察者): Observable 是一个 可以发送消息的数据源 , 可以同时发送若干消息 , 消息的格式可以通过泛型进行定义 ; 消息发送完毕后 会 通知观察者。Observable 通过 订阅观察者 来实现 消息的传递。

Observable observable = Observable.just("Hello", "World");

3、Observable 被观察者订阅 Observer 观察者

Subscription(订阅): 订阅是 Observer 对 Observable 的绑定, 它表示观察者正在接收 Observable 的数据项。 订阅可以被取消, 取消订阅后 Observer 观察者将不再接收 Observable 被观察者 的消息。

调用 Observable 被观察者 的 subscribe 函数 , 订阅 Observer 观察者 ;

该订阅操作的同时 , 会将消息发送给 Observer 观察者 , 触发 Observer#onNext 函数 ;

observable.subscribe(observer);

二、代码示例

import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
​
public class Main {
    public static void main(String[] args) {
        Observable observable = Observable.just("Hello", "World", "RxJava");
​
        Observer observer = new Observer() {
            @Override
            public void onSubscribe(Disposable d) {
                // 当观察者订阅时的回调
            }
​
            @Override
            public void onNext(String value) {
                // 当接收到新的事件时的回调
                System.out.println(value);
            }
​
            @Override
            public void onError(Throwable e) {
                // 当发生错误时的回调
            }
​
            @Override
            public void onComplete() {
                // 当事件流结束时的回调
            }
        };
​
        observable.subscribe(observer);
    }
}
​

执行结果 :

Hello
World
RxJava

4,线程控制(略)

5,变换(略)

Retrofit与RxJava的联合封装

1,封装后的网络请求示意图Android项目实战开发-----期末总结2_第3张图片

2,引入(略)

3,封装的公共部分(略)

你可能感兴趣的:(android,java)