1 HttpURLConnectionの実装
ネットワーク リクエストを行うとき、ユーザーはリクエストの権限を決定し、ネットワーク リクエストの権限を XML に追加する必要があります。
<uses-permission android:name="android.permission.INTERNET"/>
ネットワークリクエストのシンプルな実装
class HttpURLConnectionTest:AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.internet_layout)
//第一种请求网络的方式HttpURLConnection
get_date_by_url.setOnClickListener(){
sendRequestWithHttpUrl()
}
}
private fun sendRequestWithHttpUrl(){
thread{
var connection:HttpURLConnection?=null
try{
val response=StringBuilder()
val url= URL("https://www.baidu.com")
connection=url.openConnection() as HttpURLConnection
connection.connectTimeout=8000
connection.readTimeout=8000
//指定请求方式
// connection.requestMethod="Post"
//网络输出,附带参数请求
//val output=DataOutputStream(connection.outputStream)
//output.writeBytes("username=admin&password=121231")
//网络响应输入
val input=connection.inputStream
val reader=BufferedReader(InputStreamReader(input))
reader.use{
reader.forEachLine {
response.append(it)
}
}
showResponse(response.toString())
}catch (e:Exception){
e.printStackTrace()
}finally {
//断开连接
connection?.disconnect()
}
}
}
private fun showResponse(response:String){
//此方法可以进行异步的ui界面更新
runOnUiThread {
response_data.text=response
}
}
}
2 OKHttp を使用してネットワーク要求を行う
まず、build.gradle ファイルに OkHttp 依存関係を導入し、バージョンを指定する必要があります。
//加入OKhttp的
implementation 'com.squareup.okhttp3:okhttp:4.9.0'
class HttpURLConnectionTest:AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.internet_layout)
get_date_by_okHttp.setOnClickListener(){
sendRequestWithOkHttp()
}
}
private fun sendRequestWithOkHttp(){
thread {
try {
val client= OkHttpClient()
val request= Request.Builder()
.url("https://www.baidu.com")
.build()
val response=client.newCall(request).execute()
val responseData=response.body?.string()
if(responseData!=null){
showResponse(responseData)
}
}catch (e:Exception){
e.printStackTrace()
}
}
}
private fun showResponse(response:String){
//此方法可以进行异步的ui界面更新
runOnUiThread {
response_data.text=response
}
}
}
OkHttpClient が使用されている場合は、java.lang.ExceptionInInitializerError が報告されることに注意してください。OKhttp パッケージのインポートされたバージョンに問題がある可能性があります。適切なバージョンを再度ダウンロードしてください。
3 実際のシナリオで OKHttp を記述するためのより良い方法
リクエストが比較的少ない場合は、コード内でOKHttpを直接使用することも可能ですが、リクエストが多すぎる場合、すべてのリクエストをプロジェクトコードに入れることができないため、リクエストを抽出して抽象化する必要がありますメソッドをツール クラスに追加して、より簡単な呼び出しを実現します。また、サブスレッドのタスクを実行する場合はメインスレッドに結果を返す必要があるため、データ更新にはコールバックインターフェースを使用する必要があります。
HttpURLRequest ツール クラスと OKHtttp ツール クラスをカプセル化する
HttpURLRequest を使用する場合はカスタム インターフェイスが必要です
interface HttpCallbackListener {
fun onFinish(response:String)
fun onError(e:Exception)
}
次に、メソッドをカプセル化し、ツール クラスのコールバック インターフェイスを呼び出します。
object HttpUtil {
fun sendHttpRequest(address:String,listener:HttpCallbackListener){
thread {
var connection:HttpURLConnection?=null
try{
val response=StringBuilder()
val url=URL(address)
connection=url.openConnection() as HttpURLConnection
connection.connectTimeout=8000
connection.readTimeout=8000
val input=connection.inputStream
val reader=BufferedReader(InputStreamReader(input))
reader.use {
reader.forEachLine {
response.append(it)
} }
listener.onFinish(response.toString())
}catch (e:Exception){
e.printStackTrace()
listener.onError(e)
}finally {
connection?.disconnect()
}
}
}
//使用OkHttp的方法
fun sendOKHttpRequest(address:String,callback:okhttp3.Callback){
val client=OkHttpClient()
val request=Request.Builder()
.url(address)
.build()
//在enqueue的内部已经开启了子线程
client.newCall(request).enqueue(callback)
}
手順
class HttpURLConnectionTest:AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.internet_layout)
//使用工具类进行逻辑的编写
get_date_by_util_Httpurl.setOnClickListener{
HttpUtil.sendHttpRequest("https://www.baidu.com",object :HttpCallbackListener{
override fun onFinish(response: String) {
showResponse(response)
}
override fun onError(e: Exception) {
println("在这里进行异常的处理")
}
})
}
get_date_by_util_okHttp.setOnClickListener(){
HttpUtil.sendOKHttpRequest("https://www.baidu.com",object:Callback{
override fun onFailure(call: Call, e: IOException) {
println("失败的话打印异常处理")
}
override fun onResponse(call: Call, response: Response) {
val responseData=response.body?.string()
if (responseData != null) {
showResponse(responseData)
}
}
})
}
}
private fun showResponse(response:String){
//此方法可以进行异步的ui界面更新
runOnUiThread {
response_data.text=response
}
}
}
4 つのより強力な Retrofit フレームワーク
Retrofit は、OKHttp をベースにした包括的なフレームワークであり、より優れたデータ要求仕様と応答仕様を備えています。
依存ライブラリに参加するには 0
implementation 'com.squareup.retrofit2:retrofit:2.6.1'
implementation 'com.squareup.retrofit2:converter-gson:2.6.1'
1 GSON を使用して返されたオブジェクトをマッピングするためのエンティティ クラスを作成します
class Student(val id:Int,val name:String,val className:String) {
}
2 さまざまなリクエスト パスの戻りを処理するサービス インターフェイスを作成します。
interface StudentService {
//这里指定了网站下具体的资源地址
@GET("gete.json")
fun getStudentInfo(): Call<List<Student>>
}
3 Retrofit を使用して返されたデータを処理する
use_Retrofit.setOnClickListener(){
val retrofit=Retrofit.Builder()
//会和Service中的地址进行组合,来确定成为一个唯一的请求地址
.baseUrl("基础地址")
.addConverterFactory(GsonConverterFactory.create())
.build()
val studentService=retrofit.create(StudentService::class.java)
studentService.getStudentInfo().enqueue(object:retrofit2.Callback<List<Student>>{
override fun onResponse(
call: retrofit2.Call<List<Student>>,
response: retrofit2.Response<List<Student>>
) {
val students=response.body()
if(students!=null){
for(student in students){
println("输出学生的信息${
student.id}等即可")
}
}
}
//处理异常
override fun onFailure(call: retrofit2.Call<List<Student>>, t: Throwable) {
t.printStackTrace()
}
})
}
4 その他のリクエスト状況に対する解決策
interface StudentService {
//这里指定了网站下具体的资源地址
@GET("/user/Student/getStudent.json")
fun getStudentInfo(): Call<List<Student>>
//处理路径中带有可变参数的情况,关键词Path
@GET("{page}/getStudent.json")
fun getStudentInfoByPage(@Path("page") page:Int):Call<List<Student>>
//处理Get请求时路径中带有参数的情况关键词Query
@GET("/user/Student/getStudent.json")
fun getStudentInfoByNameAndClassName(@Query("name") name:String,@Query("calssName") className:String):Call<List<Student>>
//按照id删除一个学生,如果对返回值不关心,就是用Call<ResponseBody>代替
@DELETE("/user/Student/{id}")
fun deleteById(@Path("id") id:Int):Call<ResponseBody>
//如果想要提交数据,直接按照对象进行提交
@POST("user/Student")
fun createStudent(@Body student:Student):Call<ResponseBody>
//如果希望在请求头header中加入请求参数,就按照键值对的方式进行填充数据静态方式
@Headers("User-Agent:okHttp","Cache-Control:max-age=0")
@GET("地址")
fun getStudentBy():Call<Student>
//动态
@GET("地址2")
fun getStudentByDynamic(
@Header("User-Agent") userAgent:String,
@Header("Cache-Control") cache_control:String):Call<Student>
}
}
Retrofit を使用すると作成プロセスが複雑すぎるため、ツールを使用します。
ツールスタックでの処理
object ServiceCreator {
private const val BASE_URL="自己的基础访问地址"
private val retrofit=Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
//只提供一个方法即可对外返回创建的Service实例
fun <T> create(serviceClass: Class<T>):T= retrofit.create(serviceClass)
}
手順
use_Retrofit.setOnClickListener(){
/*val retrofit=Retrofit.Builder()
.baseUrl("基础地址")
.addConverterFactory(GsonConverterFactory.create())
.build()*/
val studentService=ServiceCreator.create(StudentService::class.java)
studentService.getStudentInfo().enqueue(object:retrofit2.Callback<List<Student>>{
override fun onResponse(
call: retrofit2.Call<List<Student>>,
response: retrofit2.Response<List<Student>>
) {
val students=response.body()
if(students!=null){
for(student in students){
println("输出学生的信息${
student.id}等即可")
}
}
}
//处理异常
override fun onFailure(call: retrofit2.Call<List<Student>>, t: Throwable) {
t.printStackTrace()
}
})
}