Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Android

วิธีใช้ Volley String Request ใน Android

ภาพรวม

ตัวอย่างนี้สาธิตการใช้ StringRequest ของ Volley Library สำหรับ HTTP Request แบบ GET เพื่อดึงข้อมูล JSON/String จาก Server คล้ายกับ ID 1004061234 แต่เน้นรายละเอียด StringRequest โดยเฉพาะ

ขั้นตอนการสร้างโปรเจกต์

ขั้นตอนที่ 1: สร้างโปรเจกต์ใหม่

Android Studio → File → New Project → Empty Activity

ขั้นตอนที่ 2: เพิ่ม Dependency (build.gradle)

dependencies {
    implementation 'com.android.volley:volley:1.2.1'
    implementation 'com.android.support:appcompat-v7:28.0.0'
}

ขั้นตอนที่ 3: Layout (res/layout/activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:textSize="16sp"
        android:gravity="center"
        android:padding="16dp"
        android:text="Loading..." />

</LinearLayout>

ขั้นตอนที่ 4: โค้ดหลัก (src/MainActivity.java)

package com.example.myapplication;

import android.os.Build;
import android.os.Bundle;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;

public class MainActivity extends AppCompatActivity {

    TextView textView;
    RequestQueue queue;
    String URL = "https://jsonplaceholder.typicode.com/posts/1";

    @RequiresApi(api = Build.VERSION_CODES.N)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = findViewById(R.id.text);
        queue = Volley.newRequestQueue(this);

        // StringRequest - GET
        StringRequest stringRequest = new StringRequest(Request.Method.GET, URL,
            new Response.Listener<String>() {
                @Override
                public void onResponse(String response) {
                    // Response มาเป็น Raw String (JSON Text)
                    textView.setText("Raw Response:\n" + response);
                    
                    // Parse JSON เองหากต้องการ
                    try {
                        JSONObject json = new JSONObject(response);
                        String title = json.getString("title");
                        String body = json.getString("body");
                        textView.append("\n\n---\nParsed:\nTitle: " + title + "\nBody: " + body);
                    } catch (JSONException e) {
                        Log.e("Volley", "Parse error", e);
                    }
                }
            },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    String errorMsg = "Error: ";
                    if (error.networkResponse != null) {
                        errorMsg += "HTTP " + error.networkResponse.statusCode;
                    }
                    errorMsg += " - " + error.getMessage();
                    textView.setText(errorMsg);
                    Log.e("Volley", errorMsg, error);
                }
            }
        ) {
            // Override getHeaders() เพื่อเพิ่ม Headers (เช่น Authorization)
            @Override
            public Map<String, String> getHeaders() throws AuthFailureError {
                Map<String, String> headers = new HashMap<>();
                headers.put("Authorization", "Bearer YOUR_TOKEN");
                headers.put("Accept", "application/json");
                return headers;
            }
            
            // Override getParams() สำหรับ POST Request
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                Map<String, String> params = new HashMap<>();
                params.put("key1", "value1");
                params.put("key2", "value2");
                return params;
            }
        };

        // ตั้งค่า Retry Policy
        stringRequest.setRetryPolicy(new DefaultRetryPolicy(
            10000, // Timeout 10 วินาที
            DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
            DefaultRetryPolicy.DEFAULT_BACKOFF_MULT
        ));

        // เพิ่ม Tag เพื่อ Cancel ได้ภายหลัง
        stringRequest.setTag("GET_POST_1");
        
        queue.add(stringRequest);
    }
    
    @Override
    protected void onStop() {
        super.onStop();
        // Cancel ทุก Request ที่มี Tag นี้ เมื่อ Activity หยุด
        queue.cancelAll("GET_POST_1");
    }
}

ขั้นตอนที่ 5: AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application android:usesCleartextTraffic="true" ...> <!-- HTTP only -->

StringRequest vs JsonObjectRequest vs JsonArrayRequest

Request TypeเหมาะสำหรับResponse Parsing
StringRequestPlain text, HTML, XML, JSON (Raw)Manual (JSONObject/JSONArray)
JsonObjectRequestJSON Object ({...})Auto (JSONObject)
JsonArrayRequestJSON Array ([...]) Auto (JSONArray)

StringRequest POST Example

StringRequest postRequest = new StringRequest(Request.Method.POST, LOGIN_URL,
    response -> { /* Success */ },
    error -> { /* Error */ }
) {
    @Override
    protected Map<String, String> getParams() {
        Map<String, String> params = new HashMap<>();
        params.put("username", "user123");
        params.put("password", "pass123");
        return params;
    }
    
    @Override
    public Map<String, String> getHeaders() {
        Map<String, String> headers = new HashMap<>();
        headers.put("Content-Type", "application/x-www-form-urlencoded");
        return headers;
    }
};

Volley Request Lifecycle

1. new Request() → 2. queue.add() → 3. Cache Thread (Check Cache)
    → Hit: Parse & Deliver to Main Thread
    → Miss: Network Thread → HTTP Request → Response
        → Parse → Cache → Deliver to Main Thread

แนวทางปัจจุบัน (Modern Alternative)

Retrofit + OkHttp + Coroutines (Kotlin) เป็นมาตรฐานอุตสาหกรรม:

// Retrofit Interface
interface ApiService {
    @GET("posts/{id}")
    suspend fun getPost(@Path("id") id: Int): Response<Post>
}

// Usage
lifecycleScope.launch {
    val response = apiService.getPost(1)
    if (response.isSuccessful) {
        textView.text = response.body()?.title
    }
}

ข้อควรระวัง

  • Volley Deprecated ไม่ได้ แต่ไม่ได้รับ Active Development มากนัก
  • เหมาะสำหรับ Legacy Projects หรือ Simple Requests
  • ใหญ่โปรเจกต์ใหม่ ใช้ Retrofit/Ktor + OkHttp + Coroutines/RxJava
  • StringRequest ให้ Raw String ต้อง Parse เอง (Error-prone)
  • จำเป็นต้อง Cancel Request ใน onStop/onDestroy ป้องกัน Memory Leak/Update UI หลัง Destroy