You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copies bytes from an InputStream to an OutputStream.
This method buffers the input internally, so there is no need to use a BufferedInputStream.
最后使用一个PipedOutputStream关联到PipedInputStream输出
改造如下
privateInputStreamconvertStream( ByteArrayOutputStreamsource ) throwsIOException {
intlength = source.size();
PipedInputStreamin = newPipedInputStream();
PipedOutputStreamout = newPipedOutputStream(in);
newThread(newRunnable() {
publicvoidrun () {
try {
// write the original OutputStream to the PipedOutputStream// note that in order for the below method to work, you need// to ensure that the data has finished writing to the// ByteArrayOutputStreamsource.writeTo(out);
}
catch (IOExceptione) {
// logging and exception handling should go here
}
finally {
// close the PipedOutputStream here because we're done writing data// once this thread has completed its runif (out != null) {
// close the PipedOutputStream cleanlytry {
out.close();
} catch (IOExceptione) {
e.printStackTrace();
}
}
}
}
}).start();
returnin;
}
@OverridepublicSingle<ResponseBody> getImageFile(Stringurl) {
Bitmapbitmap = BitmapFactory.decodeResource(this.context.getResources(), R.drawable.picture);
ByteArrayOutputStreamstream = newByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG , 100 ,stream );
intlength = stream.size();
InputStreamin;
try {
in = this.convertStream(stream);
}
catch (Exceptionex){
returnfakeException(ex);
}
Sourcesource = Okio.source(in);
BufferedSourcebufferedSource = Okio.buffer(source);
ResponseBodybody = newRealResponseBody("image/jpeg",length,bufferedSource);
returnthis.delegate.returningResponse(body).getImageFile(url);
}
序言
接上一篇的博客 Http神器组件Retrofit的使用(二)——mock in Retrofit
的基础上对Retrofit的mock做一下完善收尾,可以对Retrofit的用法暂时收个尾。
上次mock以及解决的问题
本博客将解决以下问题,从小到大排列
这个点一时是我的一个痒点,因为上次我是用byte[] 做“中介”来中转啦,非常浪费内存和性能,虽然一张图片也没多大,但是还是想要写一个相对精致一点的解决方案。 我们都是讲究人嘛
虽然正常系mock以及完美实现了demo数据,做一个用不出错的数据“提供商”。但是正式环境谁都不能保证不出异常。针对异常mock也是对mock功能很好的补充,可能针对UT测试显得更有意义一些
这也是我的终极目的,我们博客都是我们实际中遇到的问题和假想,然后再做提炼,以这个demo程序作为“理想模型”为试验田,最终的结论还是要反哺到我们的项目中
从OutputStream到InputStream
从直觉来说我OutputStream流出来,直接再到InputStream流进去不是很顺,一点难度没有嘛
你的直觉骗了你
其实 这Output 和 Input 参照物是程序
OutputStream 方向= app -> io 动作 = write
InputStream 方向= io -> app 动作 = read
commio有流复制的api不过方向是反的!
Copies bytes from an InputStream to an OutputStream.
This method buffers the input internally, so there is no need to use a BufferedInputStream.
最后使用一个PipedOutputStream关联到PipedInputStream输出
改造如下
至少避免了中间数组的尴尬
相关参考
How to convert OutputStream to InputStream?
通过mock“精确”制造异常
这让我想到一部神片
电影里面的技术出神入化,把谋杀做成意外神不知鬼不觉。
在程序的时间,要“制造”指定的异常在没有合适工具的前提下也比较麻烦,难道还要拔网线,服务端“配合”你一下吗。
Retrofit的mock组件不需要电影里面这么“高”的技术含量
我们通过调用retrofit2.mock.Calls的静态方法
结果
输出
嘿,这异常输出以假乱真,和“真的”404没啥区别
参考
Retrofit 2 – Mocking HTTP Responses
实现一个mock可配置化的抽象类
架构图
从架构上来讲,我们基本上是实现填色区域内
目前Retrofit实现的UML图
已经可以对http的真实数据有个很好的交互
设计思路延续上一版,提取了一个ApiAccess接口和一个关键的MockApiAdapter抽象层,设计目的是这个类可以实现mock和真实数据的自由切换
保持不变,增加了ApiAccess的implements 实现约束
这里api获取的参数单一造成了api可以再构造里面一次成型,所以标记了final
api协议层抽象获取接口
最承上启下的核心抽象类来了
T:代表就是apiClasss类参数
V:代表mock apiClasss的类,当然本身也继承T
构造函数:其他都介绍过了,mock是新增的是否mock数据的开关标志位,由派生类决定,构造函数生成下BehaviorDelegate
createMockService:这是一个抽象方法,因为MockService和真实的Service单一构造性不同,mock可能还需要一些其他的依赖,所以我这里就不限制,让派生类类来provide,这样可以最大灵活性
getApi:这个函数我特意Override了,因为是在mock开关关的时候是执行base.getApi的,但是mock开关打开的时候是调用createMockService实现的,这里特殊点,api不能再构造函数内完成,本类并不能实现api的独立构造。所以api的获取只能采取layz load的模式,加了双锁避免重复生成
双判断+lock+lazy load参考
接下来介绍下,具体适配实现类
其他的写法上没有任何变化,这样代码重构可以省力很多,ViewModel更不需要动了
没啥亮点,还算干净整洁吧,其中mock变量以后可以用配置文件的参数来替代
完
The text was updated successfully, but these errors were encountered: