Android Volley 基本使用

2023-01-12 18:00:43

Android Volley 基本使用

本篇主要介紹 Google 給Android 平臺提供的 Volley 一個 Http請求庫 , 齊射!

1.概述

Volley是Google 提供的一個小巧的非同步請求庫,擴充套件很強支援okhttp,(預設是 Android2.3 及以上基於 HttpURLConnection,2.3 以下基於 HttpClient 實現), Volley 英文齊射的意思 就是指無數急促的請求,適合資料量小,並且通訊頻繁的場景

官方檔案 https://google.github.io/volley/

2.準備工作

想通過 volley 呼叫一個我自己的部落格文章介面 然後展示標題 和 短描述 到 頁面上

2.1 編寫佈局檔案

上面展示標題 下面展示 短描述

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/showTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        android:textStyle="bold"
        android:textSize="25sp"
        android:textColor="@color/black"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.2" />

    <TextView
        android:id="@+id/showShortDesc"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        android:textSize="18sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/showTitle"
        app:layout_constraintVertical_bias="0.2" />


</androidx.constraintlayout.widget.ConstraintLayout>

2.2 提供部落格介面地址

#隨便找了我的一篇部落格的 請求地址
https://www.askajohnny.com/blogs/blogInfo/303/15

2.3 通過JSON To Kotlin Class 外掛生成 data class (kotlin)

和 IDEA 中 Json Formatter外掛類似,它是生成JAVA的, 而這個 JSON To Kotlin Class 外掛是用來生成kotlin 的資料類的

右擊檔案 Generate.. 或者 control + 回車 喚起轉化視窗

package com.johnny.volleydemo

data class BlogInfo(
    val code: Int,
    val `data`: Data,
    val msg: String
)

data class Data(
    val anchors: List<Anchor>,
    val blogContent: String,
    val blogImageUrl: String,
    val blogMdContent: String,
    val blogShortContent: String,
    val blogTitle: String,
    val blogTypeAnchor: Any,
    val blogTypeId: String,
    val blogTypeName: Any,
    val clickCount: Int,
    val createDate: String,
    val createMonth: Any,
    val createTime: String,
    val createUser: Any,
    val id: Int,
    val isThumbed: String,
    val nextBlogId: Any,
    val nextBlogTitle: Any,
    val previousBlogId: Any,
    val previousBlogTitle: Any,
    val thumbCount: Int,
    val updateTime: String
)

data class Anchor(
    val anchorId: String,
    val anchorName: String
)

3.引入依賴

根據你的dsl 語言 選擇適合的方式引入依賴

Groovy

dependencies {
    implementation 'com.android.volley:volley:1.2.1'
}

Kotlin

dependencies {
    implementation("com.android.volley:volley:1.2.1")
}

4.傳送請求

使用 volley 需要先構建一個請求, 並且把請求提交到 newRequestQueue 佇列中, 提交後 volley 會根據構建的請求非同步傳送請求, 只需要在回撥的地方處理請求的響應即可

4.1 StringRequest 構建請求

volley 提供了 StringRequest 構建請求

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val titleTextView = findViewById<TextView>(R.id.showTitle)
        val shortDescTextView = findViewById<TextView>(R.id.showShortDesc)

        //使用 volley需要建立一個Queue
        val requestQueue = Volley.newRequestQueue(this)
        //請求的 部落格 url
        val url =
            "https://www.askajohnny.com/blogs/blogInfo/303/15"
        //構建StringRequest請求
        val stringRequest = StringRequest(Request.Method.GET,
            url, {
                //由於我後端沒有在header 的 charset中返回 UTF-8 所以預設當做ISO-8859-1格式
                //所以這裡需要先轉化成 UTF-8
                val data = String(
                    it.toByteArray(Charsets.ISO_8859_1),
                    Charsets.UTF_8
                )
                Log.d(TAG, "onCreate: stringRequest  ${data}")
                //通過Gson轉化 成上面生成的 資料類
                val blogInfo = Gson().fromJson(data, BlogInfo::class.java)
                //把後端返回的資料 展示在 textview上
                titleTextView.text = blogInfo.data.blogTitle
                shortDescTextView.text = blogInfo.data.blogShortContent
            }, {
                Log.d(TAG, "onCreate: stringRequest error ${it.message}")
            })
        //把請求推入 queue 會自動進行非同步請求
        requestQueue.add(stringRequest)
    }

效果如下..

4.2 JsonObjectRequest 構建請求

按照 JSONObject 獲取資料

第二個引數 null 表示Get請求 第二個引數如果有設定 則是post方式

GET 請求

 override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val titleTextView = findViewById<TextView>(R.id.showTitle)
        val shortDescTextView = findViewById<TextView>(R.id.showShortDesc)

        //val url = "https://weather.api.bdymkt.com/day?city=無錫"
        //
        val requestQueue = Volley.newRequestQueue(this)
        val url =
            "https://www.askajohnny.com/blogs/blogInfo/303/15"
        val postRequest = object : JsonObjectRequest(url, null,
            {
                Log.d(TAG, "volleyInitData: request success $it")
                titleTextView.text = it.getJSONObject("data").get("blogTitle") as String?
                shortDescTextView.text = it.getJSONObject("data").get("blogShortContent") as String
            }, {
                Log.d(TAG, "volleyInitData: request error ${it.message}")
            }) {
            override fun getHeaders(): MutableMap<String, String> {
                val headers = mutableMapOf<String, String>()
                headers["Accept"] = "application/json"
                headers["Content-Type"] = "application/json; charset=UTF-8"
                return headers
            }
        }
        requestQueue.add(postRequest)
    }

POST請求

此時 第二個引數設定了JSONObject() 是 post方式

        val jsonObject = JSONObject()
        jsonObject.put("pageNumber", 0)
        jsonObject.put("pageSize", 20)
        val jsonArray = JSONArray()
        jsonObject.put("ids", jsonArray)
				//此時 第二個引數設定了 是 post方式 
        val postRequest = object : JsonObjectRequest(requestUrl, jsonObject, {
            Log.d(TAG, "volleyInitData: jsonstr:$it")
            val jsonStr = it.toString()
            val blogInfo = Gson().fromJson(jsonStr, BlogInfo::class.java)
            blogAdapter.list
                .addAll(blogInfo.data.content)
            blogAdapter.notifyDataSetChanged()
        }, {
            Log.d(TAG, "volleyInitData: request error ${it.message}")
        }) {
            override fun getHeaders(): MutableMap<String, String> {
                val headers = mutableMapOf<String, String>()
                headers["Accept"] = "application/json";
                headers["Content-Type"] = "application/json; charset=UTF-8";
                return headers
            }
        }

5. 擴充套件

5.1 新增 Header 和 Params

注意 需要object: 進行匿名內部類, 重寫 getHeaders getParams getPriority 等等方法

//注意 需要object: 進行匿名內部類,  重寫 getHeaders  getParams 方法
val stringRequest = object : StringRequest(Request.Method.GET,
    url, {
        val data = String(
            it.toByteArray(Charsets.ISO_8859_1),
            Charsets.UTF_8
        )
        Log.d(TAG, "onCreate: stringRequest  ${data}")
        val blogInfo = Gson().fromJson(data, BlogInfo::class.java)
        titleTextView.text = blogInfo.data.blogTitle
        shortDescTextView.text = blogInfo.data.blogShortContent
    }, {
        Log.d(TAG, "onCreate: stringRequest error ${it.message}")
    }) { //最後面 大括號 裡面是匿名內部類重新方法
    override fun getHeaders(): MutableMap<String, String> {
        //返回 map map裡面新增 需要放入Header的資料
        return super.getHeaders()
    }

    override fun getParams(): MutableMap<String, String>? {
        //返回 map map裡面新增 需要新增的 query params
        return super.getParams()
    }
     //指定 優先順序
     override fun getPriority(): Priority {
        return Priority.HIGH
     }
}

5.2 取消佇列中的請求

如果想把佇列中的請求取消 , 需要給請求設定一個 tag , 然後呼叫佇列的 cancelAll 可以把指定tag的請求取消了

 //...

 stringRequest.setTag("obj");
 queue.add(objRequest);
        //取消請求
 queue.cancelAll("obj");

總結

本篇主要介紹 andriod 中 Volley的基本使用方式,它是官方開發的一個HTTP框架 簡化操作 , Volley 的設計目標就是非常適合去進行資料量不大,但通訊頻繁的網路操作,而對於巨量資料量的網路操作,比如說下載檔案等,Volley的表現就會非常糟糕

亂碼問題參考:

https://blog.csdn.net/yangbiyao/article/details/51270839

歡迎大家存取 個人部落格 Johnny小屋
歡迎關注個人公眾號