參考資料 ----
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()
}
}
