网络架构测试
1. 联网权限,非危险权限,xml声明即可
2. Volley架构
- 总体操作
1)创建一个队列,可以封装为单例Singleton(队列较耗资源)
2)创建请求,将其加入队列,volley通过参数回调执行返回结果即可
implementation ‘com.android.volley:volley:1.1.1’
-
样例测试
1)设置布局textView在设置scrollview滚动条布局中,保证放得下
2)新建请求选择StringRequest方法,两个构造函数,其中的一个四/三参数的可以指定请求(Request分两类为StringRequest和GsonRequest)
a. 请求方式,获取或上传(三参数不设置这次)
b. 请求网站
c. 成功回调
d. 错误回调,这两个回调简写就是类lambda表达式,如果用Kotlin写,第一个参数不能指定,找不到Method (暂时原因不明) -
测试结果,注意Volley传送门里作者写的,添加网络请求权限,这个不属于危险权限之一
-
修改获取网上图片(Volley图片加载)
1)改写第二步的请求,使用ImageLoader,第一个参数是请求队列(暂时用不到,第二个建立个cache缓存,内部方法有get和put方法(如果本地有了就拿缓存,具体不处理也能达到一点效果)
2)该对象设置了请求队列,使用get方法传入url和监听对象,并且直接内部成功/失败回调,setImageBitmap代码中设定图片
ImageLoader imageLoader=new ImageLoader(mQueue, new ImageLoader.ImageCache() {
//建立缓存 设置最大缓存量
private LruCache<String,Bitmap> cache=new LruCache<>(50);
@Override
public Bitmap getBitmap(String url) {
return cache.get(url);
}
@Override
public void putBitmap(String url, Bitmap bitmap) {
cache.put(url,bitmap);
}
});
imageLoader.get(url, new ImageLoader.ImageListener() {
@Override
public void onResponse(ImageLoader.ImageContainer response, boolean isImmediate) {
imageView.setImageBitmap(response.getBitmap());
}
@Override
public void onErrorResponse(VolleyError error) {
}
});
ps:改为Volley自带的NetworkImageview控件,不用监听的话也可以这样写
2.5.Glide组件
非网络架构,但真的很好用,就放同级了
implementation ‘com.github.bumptech.glide:glide:4.11.0’
annotationProcessor ‘com.github.bumptech.glide:compiler:4.11.0’
- 在原第二步基础上改下,就能达到同样效果,这岂不是美滋滋,并且智能缓存,还有更多个性化的操作
Glide.with(this)
.load(url)
.placeholder(R.drawable.ic_launcher_background)//占位符
.listener(new RequestListener<Drawable>() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
return false;
}
@Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
return false;
}
})
.into(imageView);
3. okhttp
- 注意8.0以后。http需要另外配置文件
- 线程问题, 在4.0之后在主线程里面执行Http请求都会报这个错,大概是怕Http请求时间太长造成程序假死的情况吧。
1. post方法
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
send_request.setOnClickListener {
//1.需要一个client
sendRequestWithOkHttp();
}
}
fun sendRequestWithOkHttp() {
Thread {
try {
//1.建立okhttpclient
val client = OkHttpClient()
//2.发起请求,需要创建一个request对象
val request: Request = Request.Builder()
.url("http://www.baidu.com")
.build()
//3.调用OkHttpClient的newCall()方法 创建一个Call对象, 并调用它的execute()方法
//来发送请求并获取服务器返回的数据
val response = client.newCall(request).execute()
val responseData = response.body().string()
println("1111111"+responseData)
response_text.text=responseData
} catch (e: Exception) {
e.printStackTrace()
}
}.start()
}
}
2. Get方法[多一个请求体]
- 由於在子綫程建立的okhttp請求,这边使用runOnUiThread在主线程更新。共两种方式
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
send_requestbyget.setOnClickListener {
//1.需要一个client
sendRequestWithOkHttpByGet();
}
send_requestbypost.setOnClickListener {
sendRequestWithOkHttpByPost();
}
}
fun sendRequestWithOkHttpByGet() {
Thread {
try {
//1.建立okhttpclient
val client = OkHttpClient()
//2.发起请求,需要创建一个request对象
val request: Request = Request.Builder()
.url("http://www.baidu.com")
.build()
//3.调用OkHttpClient的newCall()方法 创建一个Call对象, 并调用它的execute()方法
//来发送请求并获取服务器返回的数据
val response = client.newCall(request).execute()
val responseData = response.body().string()
showResponse(responseData)
} catch (e: Exception) {
e.printStackTrace()
}
}.start()
}
fun sendRequestWithOkHttpByPost() {
Thread {
try {
//1.建立okhttpclient
val client = OkHttpClient()
//2.发起请求,需要创建一个request对象
//2.5请求体
val requestBody: RequestBody = FormBody.Builder()
.add("username", "admin")
.add("password", "123456")
.build()
val request: Request = Request.Builder()
.url("https://www.jd.com")
.post(requestBody)
.build()
//3.调用OkHttpClient的newCall()方法 创建一个Call对象, 并调用它的execute()方法
//来发送请求并获取服务器返回的数据
val response = client.newCall(request).execute()
val responseData = response.body().string()
showResponse(responseData)
} catch (e: Exception) {
e.printStackTrace()
}
}.start()
}
private fun showResponse(response: String) {
runOnUiThread {
// 在这里进行UI操作, 将结果显示到界面上
response_text.setText(response)
}
}}
3.5 封装Okhttp实现自身接口回调,不然得自己写一个接口,也不难。但okhttp自带了
//普通类的静态方法
public class HttpUtil {
public static void sendOkHttpRequest(String address, okhttp3.Callback callback) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(address)
.build();
client.newCall(request).enqueue(callback);
}
}
//调用时
HttpUtil.sendOkHttpRequest("http://www.baidu.com", new okhttp3.Callback() {
@Override
public void onResponse(Call call, Response response) throws IOException {
// 得到服务器返回的具体内容
String responseData = response.body().string();} @
Override
public void onFailure(Call call, IOException e) {
// 在这里对异常情况进行处理
}
});
4. Retrofit2转载出处
1. Sample
2. 导包
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
3. 使用了注解与自定义拼接字
- 请求方法注解如get,post等等
- 请求头注解
- 请求参数注解,如Body,post,uri
- 请求和响应格式(标记)注解
4 . 优秀的数据解析
5. 同步与异步发送网络请求
6. 实现回调接口
4.5 Retrofit演示
- 建立一个Data数据类专门用于处理回调,其中
data为泛型
class Data<T> {
var code = 0
var message: String? = null
var data: T? = null
private set
fun setData(data: T) {
this.data = data
}
}
- 建立泛型对应之一的Info,这个是要根据APi来创建的
class Info {
var name: String? = null
var url: String? = null
var picurl: String? = null
}
- 创建API类
interface Api {
//get请求
@GET("api/rand.music")
fun getJsonData(
@Query("sort") sort: String?,
@Query("format") format: String?
): Call<Data<Info?>?>?
//post请求 // 请求格式注解,请求实体是一个From表单,每个键值对需要使用@Field注解
@FormUrlEncoded
@POST("api/comments.163")
fun postDataCall(@Field("format") format: String?): Call<Any?>?
}
- Main调用
1)get这边指定了回调类为Data的泛型Info
2)post这边直接接收了any。。。比较神奇
class MainActivity : AppCompatActivity() {
companion object {
private val TAG = MainActivity::class.java.simpleName
}
private var mRetrofit: Retrofit? = null
var api:Api ?=null
/**
* @param savedInstanceState
*/
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
步骤4:构建Retrofit实例
//设置网络请求BaseUrl地址 Retrofit把网络请求的URL 分成了两部分设置 第一部分:在创建Retrofit实例时通过.baseUrl()设置,
//第二部分:在网络请求接口的注解设置,就是在上面的APi接口中用GET注解的字符串: @GET("api/rand.music") 及两个query
//进行拼接:https://api.uomg.com/api/rand.music?sort=&format=
//然后通过addConverterFactory设置数据解释器,这里添加的是Gson解释器。这是为了使来自接口的json结果会自动解析成定义好的字段和类型都相符的json对象接受类
mRetrofit = Retrofit.Builder()
.baseUrl("https://api.uomg.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
// 步骤5:创建网络请求接口API对象实例
api = mRetrofit!!.create(Api::class.java)
btn1.setOnClickListener{
jsonData
}
btn2.setOnClickListener{
postJsonData()
}
}//步骤8:请求处理,输出结果// 步骤5:创建网络请求接口对象实例
//步骤6:对发送请求进行封装,传入接口参数
//步骤7:发送网络请求(异步)
/**
* 示例,get加载Json数据
*/
private val jsonData: Unit
private get() {
//这种东西访问不到外面的实例的
//步骤6:对发送请求进行封装,传入接口参数
val jsonDataCall = api?.getJsonData("新歌榜", "json")
//步骤7:发送网络请求 同步执行 要自己写接口比较麻烦
//Response<Data<Info>> execute = jsonDataCall.execute();
//步骤7:发送网络请求(异步) enqueue???、timer用的是schedule
/*
//异步请求
dataCall.enqueue(new Callback<Data<Info>>() {
//请求成功回调
@Override
public void onResponse(Call<Data<Info>> call, Response<Data<Info>> response) {
}
//请求失败回调
@Override
public void onFailure(Call<Data<Info>> call, Throwable t) {
}
});
* */
//对异步返回的数据进行处理,网络加载完成。get的请求地址为:https://api.uomg.com/api/rand.music?sort=%E6%96%B0%E6%AD%8C%E6%A6%9C&format=json
Log.e(TAG, "get == url:" + jsonDataCall!!.request().url())
jsonDataCall.enqueue(object : Callback<Data<Info?>?> {
@SuppressLint("SetTextI18n")
override fun onResponse(call: Call<Data<Info?>?>, response: Response<Data<Info?>?>) {
//步骤8:请求处理,输出结果
Toast.makeText(this@MainActivity, "get回调成功:异步执行", Toast.LENGTH_SHORT).show()
val body = response.body() ?: return
val info: Info = body.data ?: return
tv!!.text = """返回的数据:${
info.name} ${
info.picurl}
""".trimIndent()
}
override fun onFailure(call: Call<Data<Info?>?>, t: Throwable) {
Log.e(TAG, "get回调失败:" + t.message + "," + t.toString())
Toast.makeText(this@MainActivity, "get回调失败", Toast.LENGTH_SHORT).show()
}
})
}
/**
* 示例,Post加载Json数据
*/
private fun postJsonData() {
//步骤6:对发送请求进行封装:传入参数
val call = api?.postDataCall("JSON")//调用api实施的post方法
if (call != null) {
call.enqueue(object : Callback<Any?> {
@SuppressLint("SetTextI18n")
override fun onResponse(call: Call<Any?>, response: Response<Any?>) {
//步骤8:请求处理,输出结果
val body = response.body() ?: return
tv.setText("""返回的数据: ${
response.body().toString()}""".trimIndent()
)
Toast.makeText(this@MainActivity, "post回调成功:异步执行", Toast.LENGTH_SHORT).show()
}
override fun onFailure(call: Call<Any?>, t: Throwable) {
Log.e(TAG, "post回调失败:" + t.message + "," + t.toString())
Toast.makeText(this@MainActivity, "post回调失败", Toast.LENGTH_SHORT).show()
}
})
}
}