这是一个使用rxjava,retrofit封装的网络框架

这是一个使用rxjava,retrofit封装的网络框架

Android 网络编程

详细介绍

RxjavaRetrofitNetModule

这是一个使用rxjava,retrofit封装的网络框架

一.使用方式

1.作为module导入到项目中并引用

2.设置服务器url,在Url类中设置

public class Url {
    /**
     * 请求地址
     */
    public static final String BASE_URL = "https://api.douban.com/v2/movie/";
}

3.根据自己项目的报文结构,修改HttpResult类,然后修改RxHelper类如下代码(以下为伪代码):

//根据响应结果result的值来判断成功与否,以及错误处理
if (result.getCode == 200) {
   return createData(result.getData());
} else {
   return Observable.error(new ApiException(result.getCode()));
}

4.在ApiService中配置请求接口,形如:

@GET("top250")
Observable<HttpResult<List<Subject>>> getTopMovie(@Query("start") int start, @Query("count") int count);

5.构建数据源

//获取豆瓣电影TOP 30
Observable ob = Api.getDefault().getTopMovie(0, 30);

6.请求接口,处理业务逻辑

HttpUtil.getInstance().toSubscribe(ob, new ProgressSubscriber<List<Subject>>(this) {
    @Override
    protected void _onError(String message) {
        Toast.makeText(MainActivity.this, message, Toast.LENGTH_LONG).show();
    }

    @Override
    protected void _onNext(List<Subject> list) {
        Log.e("net", "list = " + list);
        String str = "";
        for (int i = 0; i < list.size(); i++) {
            str += "电影名:" + list.get(i).getTitle() + "\n";
        }
        mText.setText(str);
    }
}, "cacheKey", ActivityLifeCycleEvent.DESTROY, lifecycleSubject, true, false, CacheMode.NET_FIRST);

二.缓存模式介绍

1.设置CacheMode

* NOCACHE,不使用缓存,强制网络,此模式下isSave和forceRefresh设置无效;

* CACHE_FIRST, 使用缓存,缓存优先,缓存过期或者无缓存使用网络,此模式下isSave推荐设置为true,forceRefresh设置为false;

* NET_FIRST, 网络优先,有缓存先展示缓存,更优雅,此模式下isSave推荐设置为true,forceRefresh为false;

2.HttpUtil类中,可修改缓存有效时间,默认10分钟

/**
* 数据缓存有效期
*/
public static final long CACHE_VALID_TIME = 60 * 1000 * 10;

3.注意点:请确保缓存key的唯一性,建议使用url作为key

4.新增了缓存时弹出loading框,之前非网络请求不会弹出loading框

三.上传文件

1.多文件上传通过HttpUtil.getInstance().upLoadFiles方法,传入服务器url,以及listFiles即可,单文件上传调用upLoadFile,传入单个文件的file即可

List<File> listFiles = new ArrayList<>();
for (int i = 0; i < uris.size(); i++) {
    File file = new File(FileUtils.getRealPathFromUri(this, uris.get(i)));
    totalBytesWritten += file.length();
    listFiles.add(file);
}

HttpUtil.getInstance().upLoadFiles(Url.BASE_UPLOAD_FILE_URL, listFiles,
        new FileUploadObserver<UploadHttpResult>() {
            @Override
            public void onUploadSuccess(UploadHttpResult result) {

                if (result == null) {
                    LogUtils.e("upload", "responseBody null");
                    return;
                }

                LogUtils.e("upload", "response = " + result.toString());

                if (result.getCode() == 100) {
                    Toast.makeText(FileActivity.this, "上传成功", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(FileActivity.this, "" + result.getMsg(), Toast.LENGTH_SHORT).show();
                }

            }

            @Override
            public void onUploadFail(Throwable e) {
                Toast.makeText(FileActivity.this, "上传失败", Toast.LENGTH_SHORT).show();
                e.printStackTrace();
            }

            @Override
            public void onProgress(int progress) {
                //单文件上传使用这个,多文件使用onMultipleProgress进行处理
            }

            @RequiresApi(api = Build.VERSION_CODES.N)
            @Override
            public void onMultipleProgress(long bytesWritten, long contentLength) {

                //上一次的值小于下一次的说明切换文件了
                if (lastBytesWritten != 0 && lastBytesWritten > bytesWritten) {
                    LogUtils.e("upload", "切换文件了");
                    currentBytesWritten += lastBytesWritten;
                }
                //每次累加会增多,不是当前下载进度
                lastBytesWritten = bytesWritten;
                int progress = (int) (100 * (lastBytesWritten + currentBytesWritten) / totalBytesWritten);

                Log.e("upload", "当前上传大小:" + currentBytesWritten + "----------多文件上传百分比:" + progress);

            }
        });

四.文件下载(单文件)

1.此方式为通用的下载方式,通过计算写入文件来监听进度,使用方式如下:

String url = "http://gdown.baidu.com/data/wisegame/458668cea5349f81/MMyingyongshangchang_10641.apk";
String fileName = "hello.apk";
String fileStoreDir = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "rxRetroStore";
String fileStoreName = fileName;

HttpUtil.getInstance().downloadFile(url, fileStoreDir, fileStoreName, new FileDownloadObserver<File>() {
    @Override
    public void onDownLoadSuccess(File file) {
        Toast.makeText(MainActivity.this, "下载完成", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onDownLoadFail(Throwable throwable) {
        Toast.makeText(MainActivity.this, "下载失败", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onProgress(int progress, long total) {
        LogUtils.e("down", "progress = " + progress);
    }
});

2.此方式为通过后台service来实现后台下载,开始下载通知栏显示通知,可以查看进度,进度通过okhttp拦截器实现,使用方式如下:

//直接传入下载链接,文件名,存储路径即可,通知栏信息的修改请在DownLoaService里修改;
String url = "http://acj3.pc6.com/pc6_soure/2018-1/com.ss.android.essay.joke_672.apk";
String fileName = "hello.apk";
String fileStoreDir = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "rxRetroStore";
String fileStoreName = fileName;

Intent intent = new Intent(MainActivity.this, DownLoadService.class);
intent.putExtra("url", url);
intent.putExtra("fileStoreDir", fileStoreDir);
intent.putExtra("fileStoreName", fileStoreName);
startService(intent);

五.其他配置或自定义

1.如果您使用其他loading样式,可以在ProgressSubscriber类中修改

2.获取网络请求信息,设置超时时间等,在OkHttpManager中操作:

// 超时时间
builder.connectTimeout(30, TimeUnit.SECONDS);// 15S连接超时
builder.readTimeout(20, TimeUnit.SECONDS);// 20s读取超时
builder.writeTimeout(20, TimeUnit.SECONDS);// 20s写入超时
// 错误重连
builder.retryOnConnectionFailure(true);

/**
    *  拦截器
*/
builder.addInterceptor(new Interceptor() {
    @Override
    public okhttp3.Response intercept(Chain chain) throws IOException {
          Request request = chain.request();
          HttpUrl.Builder authorizedUrlBuilder = request.url()
                .newBuilder();

          String token = Hawk.get("token","");

          Request newRequest = request.newBuilder()
                 //对所有请求添加请求头
                 .header("mobileFlag", "test").addHeader("t", token)
                 .method(request.method(), request.body())
                 .url(authorizedUrlBuilder.build())
                 .build();

                 return  chain.proceed(newRequest);
              }
          });

           /**
               * 此处模拟,登录返回token,访问其他接口需带上token的一种情况,可根据实际情况定义
           */
           builder.addInterceptor(new Interceptor() {
               @Override
               public Response intercept(Chain chain) throws IOException {
                    Response response = chain.proceed(chain.request());
                    Log.e("net","t = "+response.header("t"));
                    if(!TextUtils.isEmpty(response.header("t"))){
                         Hawk.put("token",response.header("t"));
                    }
               return response;
           }
    });