因为在网上找到的资源不只是一些字符串或是一些二进制数字,还是有的是可以肉眼看见的图片,那么我们在发送网络请求时拿到的是一张图片该如何显示在组件上面呢?
这就要使用到okhttp的请求返回结果的一个属性(byteStream):
var input = result.byteStream()
bitmap=BitmapFactory.decodeStream(input)
myhanlder.sendEmptyMessage(3)
结合之前学习的通过okhttp发送get异步请求方式,可以写出这样的代码:
OkhttpUtils.get().doGet(url,object :NetWorkCallBack{
override fun onSuccess(result: ResponseBody) {
//TODO("Not yet implemented")
var input = result.byteStream()
bitmap=BitmapFactory.decodeStream(input)
myhanlder.sendEmptyMessage(3)
}
override fun onFail(msg: String) {
//TODO("Not yet implemented")
Toast.makeText(this@Okhttp,"请求失败",Toast.LENGTH_SHORT).show()
}
})
这里的OkhttpUtils是经过了封装的类,所以才有两个结果状态函数(onSuccess和onFail):
1、请求的封装
之前使用这个框架的时候我使用了很多的方法,有get、json、表单,现在又有一个图片的下载,所以我就直接讲这些请求方法封装在了一个工具类里面,这里面是这样写的:
package com.example.hanlderpractice.service
import com.example.hanlderpractice.entity.NetWorkCallBack
import okhttp3.*
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody.Companion.toRequestBody
import org.json.JSONObject
import java.io.IOException
import java.util.concurrent.TimeUnit
class OkhttpUtils public constructor() {
companion object {
private var instance: OkhttpUtils? = null
get() {
if (field == null) {
field = OkhttpUtils()
}
return field
}
fun get(): OkhttpUtils {
return instance!!
}
}
private var client:OkHttpClient?=null
init {
client=OkHttpClient.Builder()
.readTimeout(5,TimeUnit.SECONDS)
.connectTimeout(5,TimeUnit.SECONDS)
.build()
}
fun doGet(url:String,netWorkCallBack: NetWorkCallBack):Unit{
var request=Request.Builder()
.url(url)
.build()
client?.newCall(request)?.enqueue(object :Callback{
override fun onFailure(call: Call, e: IOException) {
//TODO("Not yet implemented")
netWorkCallBack.onFail("请求失败")
}
override fun onResponse(call: Call, response: Response) {
//TODO("Not yet implemented")
netWorkCallBack.onSuccess(response.body!!)
}
})
}
fun doJson(url:String,jsonobject:JSONObject,netWorkCallBack: NetWorkCallBack):Unit{
var jsonstr=jsonobject.toString().toRequestBody("application/json;charset=utf-8".toMediaType())
var request: Request=Request.Builder()
.url(url)
.post(jsonstr)
.build()
client?.newCall(request)?.enqueue(object :Callback{
override fun onFailure(call: Call, e: IOException) {
//TODO("Not yet implemented")
netWorkCallBack.onFail("请求失败")
}
override fun onResponse(call: Call, response: Response) {
//TODO("Not yet implemented")
netWorkCallBack.onSuccess(response.body!!)
}
})
}
fun doForm(url:String,formBody:FormBody,netWorkCallBack: NetWorkCallBack):Unit{
var request: Request=Request.Builder()
.url(url)
.post(formBody)
.build()
client?.newCall(request)?.enqueue(object :Callback{
override fun onFailure(call: Call, e: IOException) {
//TODO("Not yet implemented")
netWorkCallBack.onFail("请求失败")
}
override fun onResponse(call: Call, response: Response) {
//TODO("Not yet implemented")
netWorkCallBack.onSuccess(response.body!!)
}
})
}
}
通过派生对象来重写这个工具类的get方法,使他只能够实例化一次,也就是常见的单例模式;
还有一个对象就是用来存储请求到的数据的接口,所以这两个返回结果状态函数是这个接口里面的:
package com.example.hanlderpractice.entity
import okhttp3.ResponseBody
interface NetWorkCallBack {
public fun onSuccess(result:ResponseBody)
public fun onFail(msg:String)
}
这是一个接口,我在调用了发送请求的方法之后就会拿到一个请求结果对象,于是我就将这个结果(工具类请求到的数据)丢在这个接口里面,我就可以再别的地方(调用工具类请求方法的类)拿到了:
var url="http://119.img.pp.sohu.com/images/blog/2007/9/28/18/15/115e6595d75.jpg"
OkhttpUtils.get().doGet(url,object :NetWorkCallBack{
override fun onSuccess(result: ResponseBody) {
//TODO("Not yet implemented")
var input = result.byteStream()
bitmap=BitmapFactory.decodeStream(input)
myhanlder.sendEmptyMessage(3)
}
就比如这里,这里使用了工具类里面的doGEt方法,而且第二个参数就是这个接口,他的成功函数里面的参数就是请求到的数据体,这时候直接创建他的字节流然后转化成bitmap对象设置到imageview组件上就可以实现图片的展示了,当然如果不是发送很多请求的话也可以直接发送get请求不用封装,这里是一样的效果的,到时候拿到数据体的字节流就可以转化为bitmap对象了;
其他的post表单请求可以同样的方法,通过这个接口来返回这个数据体;
2、设置图片
//创建弱引用handler
private class MyHanlder(var wk: WeakReference<Okhttp>): Handler(Looper.getMainLooper()){
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
wk.get()?.run {
if(msg.what==1){
Toast.makeText(this,"登录成功", Toast.LENGTH_SHORT).show()
var intent: Intent = Intent(this,MainActivity::class.java)
startActivity(intent)
}else if(msg.what==2){
}
else if(msg.what==3){
iv_header.setImageBitmap(bitmap);
}else{
Toast.makeText(this,"登录失败", Toast.LENGTH_SHORT).show()
}
}
}
}
同样的,发送请求只能在子线程,而更新界面需要发送消息,这里就是what=3的时候的消息,于是将这个通过网络数据构建成的bitmap设置到组件上面;
无论是哪一张图片,这里是样例,也可以是其他的照片,可以使用同样的方式来显示到组件上;