一、RxJava
1、什么是观察者模式
指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新
2、什么是RxJava
RxJava:a library for composing asynchronous and event-based programs using observable sequences for the Java VM
RxJava 是一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库
RxJava 是一个 基于事件流、实现异步操作的库
https://github.com/ReactiveX/RxJava
3、RxJava特点
逻辑简洁,实现优雅,使用简单
4、RxJava四个角色
被观察者(Observable) 产生事件
观察者(Observer) 接收事件并处理
订阅(Subscribe) 连接 被观察者和观察者
事件(Event)
5、步骤
1、创建被观察者,生产事件
2、创建观察者并定义相应事件行为
3、通过订阅连接观察者和被观察者
4、解除订阅!!!!!!!
6、简单例子
private void demo1() {
Observable<Integer> observable = Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
emitter.onNext(4);
emitter.onComplete();
}
});
Observer observer = new Observer() {
@Override
public void onSubscribe(Disposable d) {
Log.i("Simon", "onSubscribe");
}
@Override
public void onNext(Object o) {
Log.i("Simon", "onNext: " + o);
}
@Override
public void onError(Throwable e) {
Log.i("Simon", "onError");
}
@Override
public void onComplete() {
Log.i("Simon", "onComplete");
}
};
observable.subscribe(observer);
}
7、倒计时例子
private Disposable mDisposable;
private void demo2() {
Observable.interval(0, 1, TimeUnit.SECONDS)
.subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Long>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
mDisposable = d;
Log.i("Simon", "interval onSubscribe");
}
@Override
public void onNext(@NonNull Long aLong) {
Log.i("Simon", "interval onNext aLong: " + aLong);
if (aLong > 10) {
if (mDisposable != null) {
mDisposable.dispose();
}
}
}
@Override
public void onError(@NonNull Throwable e) {
Log.i("Simon", "interval onError e: " + e.toString());
}
@Override
public void onComplete() {
Log.i("Simon", "interval onComplete");
}
});
}
8、操作符例子
private void operatorDemo() {
//just
Observable.just(1, 2, 3, 4).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.i("Simon", "just: " + integer);
}
});
//map
Observable.just(1, 2, 3, 4).map(new Function<Integer, String>() {
@Override
public String apply(Integer integer) throws Exception {
return "i get " + integer;
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.i("Simon", "map: " + s);
}
});
//flatmap
//flatMap将一个发送事件的上游Observable变换为多个发送事件的Observables,然后将它们发射的事件合并后放进一个单独的Observable里
Observable.just("张无忌", "赵敏", "小昭").flatMap(new Function<String, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(String name) throws Exception {
List<String> list = new ArrayList<>();
for (int i = 0; i < 3; i++) {
list.add(name + ":" + i);
}
return Observable.fromIterable(list);
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(String str) throws Exception {
Log.i("Simon", "" + str);
}
});
//merge
Observable o1 = Observable.just(1, 2, 3);
Observable o2 = Observable.just(4, 5, 6);
Observable.merge(o1, o2).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer o) throws Exception {
Log.i("Simon", "merge :" + o);
}
});
}
二、Retrofit
1、什么是Retrofit
Retrofit 是一个 RESTful 的 HTTP 网络请求框架的封装,网络请求的工作本质上是 OkHttp 完成,而 Retrofit 仅负责 网络请求接口的封装
2、如何使用
1、依赖
//RxJava依赖
implementation 'io.reactivex.rxjava2:rxjava:2.2.6'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
//Retrofit依赖
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
//Gson converter gson解析
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
//RxJava2 Adapter
implementation "com.squareup.retrofit2:adapter-rxjava2:2.3.0"
//okhttp
implementation 'com.squareup.okhttp3:okhttp:3.4.1'
implementation 'com.squareup.okhttp3:logging-interceptor:3.9.1'
2、权限
<uses-permission android:name="android.permission.INTERNET"/>
3、接口定义
public interface XiaService {
// http://www.qubaobei.com/ios/cf/dish_list.php?stage_id=1&limit=20&page=1
@GET("/ios/cf/dish_list.php")
Call<Xia> getXiaService(@Query("stage_id") int stage_id, @Query("limit") int limit, @Query("page") int page);
}
4、发出请求
private void requestXia() {
Retrofit retrofit = new Retrofit
.Builder()
.baseUrl("http://www.qubaobei.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
XiaService xiaService = retrofit.create(XiaService.class);
Call<Xia> call = xiaService.getXiaService(1, 5, 2);
call.enqueue(new Callback<Xia>() {
@Override
public void onResponse(Call<Xia> call, Response<Xia> response) {
Log.i("Simon", "requestXia onResponse response: " + response.body().toString());
}
@Override
public void onFailure(Call<Xia> call, Throwable t) {
Log.e("Simon", "requestXia onFailure: " + t.toString());
}
});
}
5、加上 RxJava
public interface XiaServiceRX {
@GET("/ios/cf/dish_list.php")
Observable<Xia> getXiaService(@Query("stage_id") int stage_id, @Query("limit") int limit, @Query("page") int page);
}
private void requestXia2() {
Retrofit retrofit = new Retrofit
.Builder()
.baseUrl("http://www.qubaobei.com")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
XiaServiceRX xiaService = retrofit.create(XiaServiceRX.class);
xiaService.getXiaService(1,5,1)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Xia>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
Log.i("Simon", "requestXia2 onSubscribe");
}
@Override
public void onNext(@NonNull Xia xia) {
Log.i("Simon", "requestXia2 onNext: " + xia.toString());
}
@Override
public void onError(@NonNull Throwable e) {
Log.e("Simon", "requestXia2 onError: " + e.toString());
}
@Override
public void onComplete() {
Log.i("Simon", "requestXia2 onComplete");
}
});
}
6、下载文件
//下载回调
public interface DownloadListener {
void onStart();//下载开始
void onProgress(int progress);//下载进度
void onFinish(String path);//下载完成
void onFail(String errorInfo);//下载失败
}
//service定义,注意@Streaming和@Url
public interface DownloadService {
@Streaming
@GET
Call<ResponseBody> download(@Url String url);
}
//真正下载的地方
public class RetrofitDownloader {
private static final int BUFFER_SIZE = 8192;
public static void download(String url, final String path, final DownloadListener downloadListener) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://www.baidu.com")//和下载无关,但是需要写上一个地址
.build();
DownloadService service = retrofit.create(DownloadService.class);
Call<ResponseBody> call = service.download(url);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(@NonNull Call<ResponseBody> call, @NonNull final Response<ResponseBody> response) {
writeResponseToDisk(path, response, downloadListener);
}
@Override
public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable throwable) {
downloadListener.onFail("下载失败");
}
});
}
private static void writeResponseToDisk(String path, Response<ResponseBody> response, DownloadListener downloadListener) {
writeFileFromIS(new File(path), response.body().byteStream(), response.body().contentLength(), downloadListener);
}
private static void writeFileFromIS(File file, InputStream is, long totalLength, DownloadListener downloadListener) {
downloadListener.onStart();
if (!file.exists()) {
if (!file.getParentFile().exists())
file.getParentFile().mkdir();
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
downloadListener.onFail("新建文件失败");
}
}
OutputStream os = null;
long currentLength = 0;
try {
os = new BufferedOutputStream(new FileOutputStream(file));
byte data[] = new byte[BUFFER_SIZE];
int len;
while ((len = is.read(data, 0, BUFFER_SIZE)) != -1) {
os.write(data, 0, len);
currentLength += len;
//计算当前下载进度
downloadListener.onProgress((int) (100 * currentLength / totalLength));
}
//下载完成,并返回保存的文件路径
downloadListener.onFinish(file.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
downloadListener.onFail("下载失败 exception:" + e.toString());
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (os != null) {
os.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//ui中点击按钮开始下载
private void download() {
//网络图片
String url = "http://img21.mtime.cn/CMS/Gallery/2011/07/07/200129.45747105_900.jpg";
RetrofitDownloader.download(url, "/sdcard/hsw.jpg", new DownloadListener() {
@Override
public void onStart() {
Log.i("Simon", "onStart");
}
@Override
public void onProgress(int progress) {
Log.i("Simon", "onProgress onProgress: " + progress);
}
@Override
public void onFinish(String path) {
Log.i("Simon", "onProgress onFinish path: " + path);
}
@Override
public void onFail(String errorInfo) {
Log.i("Simon", "onProgress onFail errorInfo: " + errorInfo);
}
});
}
7、上传文件
接口定义
public interface UploadDownloadService {
@Streaming
@GET
Call<ResponseBody> download(@Url String url);
@Multipart
@POST("upload")
Call<ResponseBody> uploadFile(@Part List<MultipartBody.Part> multipartBody);
}
真正的上传
public class RetrofitUploader {
private static final String RETROFIT_BASE_URL = "http://192.168.18.6:1323/";
public void uploadFile(File file, final String fileName, final Observer<FileEntity> observer) {
RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
MultipartBody multipartBody = new MultipartBody.Builder()
.addFormDataPart("file", fileName, requestBody)
.setType(MultipartBody.FORM)
.build();
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(20, TimeUnit.MINUTES)
.readTimeout(20, TimeUnit.MINUTES)
.addInterceptor(interceptor)
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(RETROFIT_BASE_URL)
.client(okHttpClient)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
UploadDownloadService uploadDownloadService = retrofit.create(UploadDownloadService.class);
uploadDownloadService.uploadFile(multipartBody.parts())
.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
Log.e("Simon", "onResponse" + response.body());
FileEntity fileEntity = new FileEntity();
fileEntity.fileUrl = RETROFIT_BASE_URL + fileName;
observer.onNext(fileEntity);
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.e("Simon", "onFailure" + t.getMessage());
observer.onError(t);
}
});
}
public static class FileEntity {
public String fileUrl;
}
}
ui调用下载
private void upload() {
RetrofitUploader retrofitUploader = new RetrofitUploader();
retrofitUploader.uploadFile(new File("/sdcard/hsw2.jpg"), "hsw2_ha.jpg", new Observer<RetrofitUploader.FileEntity>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull RetrofitUploader.FileEntity fileEntity) {
Log.i("Simon", "uploadFile " + fileEntity.fileUrl);
}
@Override
public void onError(@NonNull Throwable e) {
}
@Override
public void onComplete() {
}
});
}
上传的服务器实现(使用echo:https://echo.labstack.com/)
package main
import (
"fmt"
"io"
"os"
"net/http"
"github.com/labstack/echo"
"github.com/labstack/echo/middleware"
)
func upload(c echo.Context) error {
// Read form fields
name := c.FormValue("name")
email := c.FormValue("email")
//-----------
// Read file
//-----------
// Source
file, err := c.FormFile("file")
if err != nil {
return err
}
src, err := file.Open()
if err != nil {
return err
}
defer src.Close()
// Destination
dst, err := os.Create(file.Filename)
if err != nil {
return err
}
defer dst.Close()
// Copy
if _, err = io.Copy(dst, src); err != nil {
return err
}
return c.HTML(http.StatusOK, fmt.Sprintf("<p>File %s uploaded successfully with fields name=%s and email=%s.</p>", file.Filename, name, email))
}
func main() {
e := echo.New()
e.Use(middleware.Logger())
e.Use(middleware.Recover())
e.Static("/", "public")
e.POST("/upload", upload)
e.Logger.Fatal(e.Start(":1323"))
}
8、注解
方法注解:@GET、@POST、@PUT、@DELETE、@PATCH、@HEAD、@OPTIONS、@HTTP
标记注解:@FormUrlEncoded、@Multipart、@Streaming
参数注解:@Query、@QueryMap、@Body、@Field、@FieldMap、@Part、@PartMap
其他注解:@Path、@Header、@Headers、@HeaderMap、@Url
@Query:URL后面有参数
@QueryMap:URL后面有多个参数
@FormUrlEncoded:是一个form表单,用于修饰@Field、@FieldMap注解,具”application / x-www-form-urlencoded” MIME类型
@Field:表单字段,需要和@FormUrlEncoded配合使用
@FieldMap:表单字段,需要和@FormUrlEncoded配合使用
@Streaming:下载使用
@Url:重新定义Url












网友评论