參考資料 ----
Volley overview
github/google/volley
Volley 是 Jetpack 的一員,能讓開發者以簡單的方式寫出與 httpclient 相同功能的程式,並且速度更快。不過 Volley 只適合輕量的網路傳輸,所以諸如檔案的下載或串流的操作,仍建議以原有的方式執行,如:DownloadManager。
在 AndroidManifest.xml 加入網路權限
- <uses-permission android:name="android.permission.INTERNET" />
- <application
- ...
- ...
在 app 層級的 build.gradle 加入相關宣告
- ...
- ...
- dependencies {
- ...
- implementation 'com.android.volley:volley:1.1.1'
- }
activity_main.xml
- <?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/textView"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="Hello World!"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintLeft_toLeftOf="parent"
- app:layout_constraintRight_toRightOf="parent"
- app:layout_constraintTop_toTopOf="parent" />
- <Button
- android:id="@+id/button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="96dp"
- android:text="Button"
- app:layout_constraintBottom_toTopOf="@+id/textView"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintHorizontal_bias="0.482"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintVertical_bias="0.07"
- android:onClick="sendrequest"/>
- </androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.kt(最陽春的範例)
- import android.app.Activity
- import android.os.Bundle
- import android.view.View
- import android.widget.TextView
- import com.android.volley.Request
- import com.android.volley.Response
- import com.android.volley.toolbox.StringRequest
- import com.android.volley.toolbox.Volley
- class MainActivity : Activity()
- {
- val TAG = "MyTag"
- override fun onCreate(savedInstanceState: Bundle?)
- {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_main)
- }
- fun sendrequest(v: View)
- {
- val queue = Volley.newRequestQueue(this)
- val url = "https://您的網址/php程式.php"
- val textView = findViewById(R.id.textView)
- val stringRequest = StringRequest(Request.Method.GET,
- url,
- Response.Listener<String> { response -> textView.text = response.toString()},
- Response.ErrorListener { error ->
- Log.d(TAG, "volley error: %s".format(error.toString()))
- textView.text = "volley error"
- }
- )
- // Add the request to the RequestQueue.
- queue.add(stringRequest)
- }
- }
app 執行後,一按 button,就會看到 TextView 顯示回傳的字串,超簡單的!
但 Google 仍強烈建議不要在主執行緒(UI thread) 執行。
方法二
新增一個 VolleyService.kt
- package 完整packagename
- import android.content.Context
- import com.android.volley.RequestQueue
- import com.android.volley.toolbox.Volley
- object VolleyService
- {
- private lateinit var context: Context
- val requestQueue: RequestQueue by lazy { Volley.newRequestQueue(context) }
- fun initialize(context: Context)
- {
- this.context = context.applicationContext
- }
- }
再新增一個 Application 級的 class:App.kt
- package 完整packagename
- import android.app.Application
- class App : Application()
- {
- override fun onCreate()
- {
- super.onCreate()
- VolleyService.initialize(this)
- }
- }
微調一下 AndroidManifest.xml
- ...
- ...
- <uses-permission android:name="android.permission.INTERNET" />
- <application
- android:name=".App"
- ...
- ...
再微調 MainActivity.kt
- ...
- ...
- fun sendrequest(v: View)
- {
- val url = "https://網址/php程式"
- val textView = findViewById(R.id.textView)
- // Request a string response from the provided URL.
- val stringRequest = StringRequest(Request.Method.GET, url,
- Response.Listener<string> { response -> textView.text = response.toString() },
- Response.ErrorListener { textView.text = "That didn't work!" }
- )
- // 呼叫 VolleyService
- VolleyService.requestQueue.add(stringRequest)
- VolleyService.requestQueue.start()
- }
Volley 也可以直接取得 json
在本例中,自網站取得的是一個 json 陣列,陣列元素組成為 exno, exname, exdate 三個字串,改用 ListView 顯示
activity_main.xml
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout
- 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">
- <Button
- android:id="@+id/button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentStart="true"
- android:layout_alignParentLeft="true"
- android:layout_alignParentTop="true"
- android:layout_marginStart="32dp"
- android:layout_marginLeft="32dp"
- android:text="get json"
- android:onClick="getjson" />
- <ListView
- android:id="@+id/lv"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_below="@id/button"
- android:layout_marginTop="10dp"
- android:layout_marginLeft="10dp"
- android:layout_marginRight="10dp" />
- </RelativeLayout>
新增 list_item.xml
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:paddingBottom="6dp"
- android:paddingLeft="6dp"
- android:paddingRight="6dp"
- android:paddingTop="6dp" >
- <TextView
- android:id="@+id/lblExno"
- android:layout_alignParentTop="true"
- android:layout_alignParentLeft="true"
- android:layout_alignParentStart="true"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="exno"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:visibility="gone"/>
- <TextView
- android:id="@+id/lblExname"
- android:layout_below="@+id/lblExno"
- android:layout_alignParentLeft="true"
- android:layout_alignParentStart="true"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="exam_name"
- android:textColor="@android:color/holo_blue_dark"
- android:textAppearance="?android:attr/textAppearanceMedium" />
- <TextView
- android:id="@+id/lblExdate"
- android:layout_alignParentLeft="true"
- android:layout_alignParentStart="true"
- android:layout_below="@+id/lblExname"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="exam_date"
- android:textColor="@android:color/holo_blue_dark"
- android:textAppearance="?android:attr/textAppearanceSmall" />
- </RelativeLayout>
新增 ListAdapter.kt
- ...
- ...
- class ListAdapter(private val activity: Activity, private val mExno: List<*>, private val mExname: List<*>, private val mExdate: List<*>) : BaseAdapter()
- {
- init
- {
- inflater = activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
- }
- override fun getCount(): Int
- {
- return mExno.size
- }
- override fun getItem(position: Int): Any
- {
- return position
- }
- override fun getItemId(position: Int): Long
- {
- return position.toLong()
- }
- override fun getView(position: Int, convertView: View?, parent: ViewGroup): View
- {
- var vi = convertView
- if (convertView == null)
- {
- vi = inflater!!.inflate(R.layout.list_item, null)
- }
- val lblExno = vi!!.findViewById<view>(R.id.lblExno) as TextView
- val lblExname = vi.findViewById<view>(R.id.lblExname) as TextView
- val lblExdate = vi.findViewById<view>(R.id.lblExdate) as TextView
- lblExno.text = mExno[position].toString()
- lblExname.text = mExname[position].toString()
- lblExdate.text = mExdate[position].toString()
- return vi
- }
- companion object
- {
- private var inflater: LayoutInflater? = null
- }
- }
MainActivity.kt
- ...
- ...
- class MainActivity : Activity()
- {
- val TAG = "MyTag"
- override fun onCreate(savedInstanceState: Bundle?)
- {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_main)
- }
- override fun onStop()
- {
- super.onStop()
- VolleyService.requestQueue?.cancelAll(TAG)
- }
- fun getjson(v: View)
- {
- val lv = findViewById(R.id.lv) as ListView
- val url = "https://網址/php程式"
- val stringRequest = JsonArrayRequest(Request.Method.GET, url, null,
- Response.Listener<JSONArray>
- {
- response -> var listExno: MutableList<String> = ArrayList()
- var listExname: MutableList<String> = ArrayList()
- var listExdate: MutableList<String> = ArrayList()
- for(x in 0..(response.length()-1))
- {
- var exam = response.getJSONObject(x)
- listExno.add(exam.getString("exno"))
- listExname.add(exam.getString("exname"))
- listExdate.add(exam.getString("exdate"))
- }
- val adapterExam = ListAdapter(this@MainActivity, listExno, listExname, listExdate)
- lv.setAdapter(adapterExam)
- },
- Response.ErrorListener
- {
- Toast.makeText(this, "That didn't work!", Toast.LENGTH_SHORT).show()
- }
- )
- // 呼叫 VolleyService
- VolleyService.requestQueue.add(stringRequest)
- VolleyService.requestQueue.start()
- }
- }