【Android-Kotlin】网络架构

网络架构测试

1. 联网权限,非危险权限,xml声明即可

在这里插入图片描述

2. Volley架构

  1. 总体操作
    1)创建一个队列,可以封装为单例Singleton(队列较耗资源)
    2)创建请求,将其加入队列,volley通过参数回调执行返回结果即可

implementation ‘com.android.volley:volley:1.1.1’

  1. 样例测试
    1)设置布局textView在设置scrollview滚动条布局中,保证放得下
    2)新建请求选择StringRequest方法,两个构造函数,其中的一个四/三参数的可以指定请求(Request分两类为StringRequest和GsonRequest)
    a. 请求方式,获取或上传(三参数不设置这次)
    b. 请求网站
    c. 成功回调
    d. 错误回调,这两个回调简写就是类lambda表达式,如果用Kotlin写,第一个参数不能指定,找不到Method (暂时原因不明)

  2. 测试结果,注意Volley传送门里作者写的,添加网络请求权限,这个不属于危险权限之一在这里插入图片描述
    在这里插入图片描述

  3. 修改获取网上图片(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’

  1. 在原第二步基础上改下,就能达到同样效果,这岂不是美滋滋,并且智能缓存,还有更多个性化的操作
 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

  1. 注意8.0以后。http需要另外配置文件
  2. 线程问题, 在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方法[多一个请求体]

  1. 由於在子綫程建立的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. 使用了注解与自定义拼接字

  1. 请求方法注解如get,post等等
  2. 请求头注解
  3. 请求参数注解,如Body,post,uri
  4. 请求和响应格式(标记)注解

在这里插入图片描述

4 . 优秀的数据解析

在这里插入图片描述

5. 同步与异步发送网络请求

在这里插入图片描述

6. 实现回调接口

在这里插入图片描述

4.5 Retrofit演示

在这里插入图片描述

  1. 建立一个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
    }
}
  1. 建立泛型对应之一的Info,这个是要根据APi来创建的
class Info {
    
    
    var name: String? = null
    var url: String? = null
    var picurl: String? = null

}

  1. 创建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?>?


}

  1. 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()
                }
            })
        }
    }

猜你喜欢

转载自blog.csdn.net/qq_38304672/article/details/106100796