Vô-lê - tham số POST / GET


81

Tôi đã xem phiên Google IO 2013 về Vô lê và tôi đang cân nhắc chuyển sang vô lê. Volley có hỗ trợ thêm tham số POST / GET để yêu cầu không? Nếu có, tôi có thể làm như thế nào?


2
Tôi không xem toàn bộ bài phát biểu chính, nhưng tôi khá chắc chắn rằng GET sẽ có thể thực hiện được chỉ bằng cách thêm các tham số vào URL (ví dụ http://example.com?param1=val1&param2=val2:)
JJJollyjim

Có vẻ như vẫn chưa có tài liệu, nhưng bạn có thể kiểm tra nguồn tại đây android.googlesource.com/platform/frameworks/volley/+/master
MM.

@ JJ56 - Đúng, nhưng còn các thông số POST thì sao? Tôi đã xem mã nguồn nhưng không tìm thấy bất kỳ thứ gì liên quan đến tham số POST.
Ziem

1
Tôi cảm thấy xấu hổ khi nói điều này. Tuy nhiên, nếu bạn đến đây hỏi tại sao yêu cầu của bạn không có phần thân trên máy chủ, hãy đảm bảo rằng bạn đang sử dụng phương thức POST / PUT. Chắc tôi chỉ mệt thôi. Hy vọng nhận xét này giúp bất cứ ai hoặc giúp tôi cảm thấy tốt hơn
Alwin Kesler

Câu trả lời:


64

Trong lớp Yêu cầu của bạn (mở rộng Yêu cầu), ghi đè phương thức getParams (). Bạn sẽ làm tương tự đối với tiêu đề, chỉ cần ghi đè getHeaders ().

Nếu bạn nhìn vào lớp PostWithBody trong TestRequest.java trong các bài kiểm tra Volley, bạn sẽ tìm thấy một ví dụ. Nó đi một cái gì đó như thế này

public class LoginRequest extends Request<String> {

    // ... other methods go here

    private Map<String, String> mParams;

    public LoginRequest(String param1, String param2, Listener<String> listener, ErrorListener errorListener) {
        super(Method.POST, "http://test.url", errorListener);
        mListener = listener;
        mParams = new HashMap<String, String>();
        mParams.put("paramOne", param1);
        mParams.put("paramTwo", param2);

    }

    @Override
    public Map<String, String> getParams() {
        return mParams;
    }
}

Evan Charlton đã đủ tốt bụng để thực hiện một dự án ví dụ nhanh để chỉ cho chúng ta cách sử dụng cú vô lê. https://github.com/evancharlton/folly/


70
Lưu ý rằng getParamschỉ được gọi (theo mặc định) trong một yêu cầu POST hoặc PUT, nhưng không được gọi trong một yêu cầu GET. Xem câu trả lời của Ogre_BGR
Itai Hanski

2
Không thể tin được là tôi chưa bao giờ nhận thấy điều đó cho đến bây giờ
Afzal N

@AfzalivE, có ý kiến ​​gì về cách ký yêu cầu API bằng OAuth khi sử dụng mã trên không?
Bipin Vayalu

2
@BipinVayalu Nếu bạn đang kết nối với Google API bạn sẽ có thể sử dụng com.android.volley.AndroidAuthenticator
Pierre-Antoine

Bạn đã quên khởi tạo mParams.
Moritz

84

Đối với các tham số GET, có hai lựa chọn thay thế:

Đầu tiên : Như được đề xuất trong một nhận xét dưới đây, câu hỏi bạn chỉ có thể sử dụng Chuỗi và thay thế các trình giữ chỗ tham số bằng các giá trị của chúng như:

String uri = String.format("http://somesite.com/some_endpoint.php?param1=%1$s&param2=%2$s",
                           num1,
                           num2);

StringRequest myReq = new StringRequest(Method.GET,
                                        uri,
                                        createMyReqSuccessListener(),
                                        createMyReqErrorListener());
queue.add(myReq);

trong đó num1 và num2 là các biến Chuỗi chứa các giá trị của bạn.

Thứ hai : Nếu bạn đang sử dụng HttpClient bên ngoài mới hơn (ví dụ: 4.2.x), bạn có thể sử dụng URIBuilder để tạo Uri của mình. Ưu điểm là nếu chuỗi tiểu của bạn đã có các tham số trong đó thì sẽ dễ dàng chuyển nó đến URIBuildervà sau đó sử dụng ub.setQuery(URLEncodedUtils.format(getGetParams(), "UTF-8"));để thêm các tham số bổ sung của bạn. Bằng cách đó, bạn sẽ không cần phải kiểm tra xem có "?" đã được thêm vào tiểu hoặc bỏ sót một số và do đó loại bỏ nguồn gây ra lỗi tiềm ẩn.

Đối với các tham số POST có lẽ đôi khi sẽ dễ dàng hơn câu trả lời được chấp nhận để làm điều đó như:

StringRequest myReq = new StringRequest(Method.POST,
                                        "http://somesite.com/some_endpoint.php",
                                        createMyReqSuccessListener(),
                                        createMyReqErrorListener()) {

    protected Map<String, String> getParams() throws com.android.volley.AuthFailureError {
        Map<String, String> params = new HashMap<String, String>();
        params.put("param1", num1);
        params.put("param2", num2);
        return params;
    };
};
queue.add(myReq);

ví dụ: chỉ ghi đè lên getParams() phương thức.

Bạn có thể tìm thấy một ví dụ làm việc (cùng với nhiều ví dụ Volley cơ bản khác) trong dự án Andorid Volley Examples .


Tôi đã theo dõi các ví dụ của bạn về Volley. Cho đến nay, đó là mã Volly hữu ích nhất, nhưng tôi gặp sự cố trong JsonObjectRequest. Tôi nhận được phản hồi cũ trong createMyReqSuccessListener cho đến khi tôi cài đặt lại nó. Volley có lưu trữ dữ liệu trong bộ nhớ cache không? Hãy đề xuất một cách để làm điều này.
SkyWalker

2
Chỉ hình ảnh được lưu vào bộ nhớ đệm. Vui lòng kiểm tra xem có proxy nào đang chặn các yêu cầu của bạn không. Nếu các yêu cầu có cùng một URL và có thể proxy chỉ trả về kết quả đầu tiên.
Ognyan

2
Có một plugin cho Firefox có tên "Kiểm tra tài nguyên HTTP" cho phép bạn gửi các yêu cầu đến máy chủ web. Nó khá hữu ích cho các trường hợp thử nghiệm như thế này. Chỉ cần nhập URL của bạn (và các thông số ĐĂNG nếu có) và xem phản hồi của máy chủ đối với nhiều yêu cầu liên tiếp là gì. Nếu một lần nữa bạn nhận được cùng một kết quả phản hồi thì rất có thể đã được lưu vào bộ nhớ đệm. Trong trường hợp đó, bạn có thể kiểm tra các tiêu đề được trả về để kiểm tra xem có tiêu đề proxy hay không. Về "no-cache" - có, nó sẽ hoạt động.
Ognyan

2
Tôi khuyên bạn nên mở câu hỏi riêng để những người khác có thể tham gia và trợ giúp. Vui lòng cung cấp thông tin bạn đang sử dụng HURL hoặc HttpClient ngăn xếp nào, cũng là phiên bản Android mà bạn đang thử nghiệm. Vui lòng đặt liên kết đến câu hỏi mới tại đây để mọi người có thể theo dõi cuộc thảo luận.
Ognyan

3
@Yousif Có thể bạn sẽ nhận được nhiều câu trả lời tốt hơn nếu bạn hỏi đây là câu hỏi mới, nhưng tóm lại: Yêu cầu POST cho phép bạn gửi tệp và dữ liệu lớn hơn khác sẽ không phù hợp với yêu cầu GET. Ngoài ra, có một rủi ro bảo mật khi sử dụng yêu cầu GET vì URL có thể được đăng nhập trên máy chủ do đó làm lộ dữ liệu nhạy cảm.
Ognyan

23

CustomRequest là một cách để giải quyết việc JSONObjectRequest của Volley không thể đăng các tham số như StringRequest

đây là lớp trợ giúp cho phép thêm các tham số:

    import java.io.UnsupportedEncodingException;
    import java.util.Map;    
    import org.json.JSONException;
    import org.json.JSONObject;    
    import com.android.volley.NetworkResponse;
    import com.android.volley.ParseError;
    import com.android.volley.Request;
    import com.android.volley.Response;
    import com.android.volley.Response.ErrorListener;
    import com.android.volley.Response.Listener;
    import com.android.volley.toolbox.HttpHeaderParser;

    public class CustomRequest extends Request<JSONObject> {

    private Listener<JSONObject> listener;
    private Map<String, String> params;

    public CustomRequest(String url, Map<String, String> params,
            Listener<JSONObject> reponseListener, ErrorListener errorListener) {
        super(Method.GET, url, errorListener);
        this.listener = reponseListener;
        this.params = params;
    }

    public CustomRequest(int method, String url, Map<String, String> params,
            Listener<JSONObject> reponseListener, ErrorListener errorListener) {
        super(method, url, errorListener);
        this.listener = reponseListener;
        this.params = params;
    }

    protected Map<String, String> getParams()
            throws com.android.volley.AuthFailureError {
        return params;
    };

    @Override
    protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
        try {
            String jsonString = new String(response.data,
                    HttpHeaderParser.parseCharset(response.headers));
            return Response.success(new JSONObject(jsonString),
                    HttpHeaderParser.parseCacheHeaders(response));
        } catch (UnsupportedEncodingException e) {
            return Response.error(new ParseError(e));
        } catch (JSONException je) {
            return Response.error(new ParseError(je));
        }
    }

    @Override
    protected void deliverResponse(JSONObject response) {
        // TODO Auto-generated method stub
        listener.onResponse(response);
    }

}

cảm ơn Greenchiu


@WarrenFaith Cảm ơn bạn đã chỉ ra, tôi đã cập nhật câu trả lời!
LOG_TAG

3
Cảm ơn rất nhiều, tôi đã tìm kiếm hàng giờ trước khi tôi nhận được giải pháp này, Thật kỳ lạ khi ghi getParams()đè hàm JSONObjectReuqest không hoạt động.
Walid Ammar

@MohammadWalid FYTôi đã đọc stackoverflow.com/questions/16902716/… và cố gắng sử dụng trang bị thêm! cả volley và trang bị thêm đều có thể được sử dụng với okhttp!
LOG_TAG

Tôi đã thử giải pháp này, nhưng không hiệu quả với tôi. getParams () không được gọi.
Mahdi

10

Lớp trợ giúp này quản lý các tham số cho các yêu cầu GETPOST :

import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.Map;    

import org.json.JSONException;
import org.json.JSONObject;

import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
import com.android.volley.toolbox.HttpHeaderParser;

public class CustomRequest extends Request<JSONObject> {
    private int mMethod;
    private String mUrl;
    private Map<String, String> mParams;
    private Listener<JSONObject> mListener;

    public CustomRequest(int method, String url, Map<String, String> params,
            Listener<JSONObject> reponseListener, ErrorListener errorListener) {
        super(method, url, errorListener);
        this.mMethod = method;
        this.mUrl = url;
        this.mParams = params;
        this.mListener = reponseListener;
    }

@Override
public String getUrl() {
    if(mMethod == Request.Method.GET) {
        if(mParams != null) {
            StringBuilder stringBuilder = new StringBuilder(mUrl);
            Iterator<Map.Entry<String, String>> iterator = mParams.entrySet().iterator();
            int i = 1;
            while (iterator.hasNext()) {
                Map.Entry<String, String> entry = iterator.next();
                if (i == 1) {
                    stringBuilder.append("?" + entry.getKey() + "=" + entry.getValue());
                } else {
                    stringBuilder.append("&" + entry.getKey() + "=" + entry.getValue());
                }
                iterator.remove(); // avoids a ConcurrentModificationException
                i++;
            }
            mUrl = stringBuilder.toString();
        }
    }
    return mUrl;
}

    @Override
    protected Map<String, String> getParams()
            throws com.android.volley.AuthFailureError {
        return mParams;
    };

    @Override
    protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
        try {
            String jsonString = new String(response.data,
                    HttpHeaderParser.parseCharset(response.headers));
            return Response.success(new JSONObject(jsonString),
                    HttpHeaderParser.parseCacheHeaders(response));
        } catch (UnsupportedEncodingException e) {
            return Response.error(new ParseError(e));
        } catch (JSONException je) {
            return Response.error(new ParseError(je));
        }
    }

    @Override
    protected void deliverResponse(JSONObject response) {
        // TODO Auto-generated method stub
        mListener.onResponse(response);
    }
}

Điều này giải quyết việc thêm các tham số vào phương thức GET, Cảm ơn bạn!
pkarc

2
Trong trường hợp của chúng tôi, cách tiếp cận trình lặp đã phá hủy đối tượng Map params ban đầu mà chúng tôi đã truyền cho hàm. Có vẻ Volley gọi nội bộ GetUrlnhiều lần. Chúng tôi đã kết thúc với một cách tiếp cận foreach cổ điển như đã đăng trong một câu trả lời riêng. Hy vọng điều này sẽ giúp những người đến đây. :)
Paolo Casciello

Làm thế nào để gọi lớp helper này cho get yêu cầu với 3 thông số
kgandroid

@kgandroid, tạo một Bản đồ <Chuỗi, Chuỗi> với các khóa và giá trị của bạn. Ví dụ: Map <String, String> params = new HashMap <String, String> (); params.put ("param1", "value1"); params.put ("param2", "value2"); params.put ("param3", "value3");
Phương châm của Andrea

6

Đối phó với các tham số GET tôi đã lặp lại trên giải pháp của Andrea Motto '. Vấn đề là Volley đã gọi GetUrlnhiều lần và giải pháp của anh ta, sử dụng một Iterator, đã phá hủy đối tượng Bản đồ gốc. Các cuộc gọi nội bộ Volley tiếp theo có một đối tượng params trống.

Tôi cũng đã thêm mã hóa các tham số.

Đây là cách sử dụng nội tuyến (không có lớp con).

public void GET(String url, Map<String, String> params, Response.Listener<String> response_listener, Response.ErrorListener error_listener, String API_KEY, String stringRequestTag) {
    final Map<String, String> mParams = params;
    final String mAPI_KEY = API_KEY;
    final String mUrl = url;

    StringRequest stringRequest = new StringRequest(
            Request.Method.GET,
            mUrl,
            response_listener,
            error_listener
    ) {
        @Override
        protected Map<String, String> getParams() {
            return mParams;
        }

        @Override
        public String getUrl() {
            StringBuilder stringBuilder = new StringBuilder(mUrl);
            int i = 1;
            for (Map.Entry<String,String> entry: mParams.entrySet()) {
                String key;
                String value;
                try {
                    key = URLEncoder.encode(entry.getKey(), "UTF-8");
                    value = URLEncoder.encode(entry.getValue(), "UTF-8");
                    if(i == 1) {
                        stringBuilder.append("?" + key + "=" + value);
                    } else {
                        stringBuilder.append("&" + key + "=" + value);
                    }
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                i++;

            }
            String url = stringBuilder.toString();

            return url;
        }

        @Override
        public Map<String, String> getHeaders() {
            Map<String, String> headers = new HashMap<>();
            if (!(mAPI_KEY.equals(""))) {
                headers.put("X-API-KEY", mAPI_KEY);
            }
            return headers;
        }
    };

    if (stringRequestTag != null) {
        stringRequest.setTag(stringRequestTag);
    }

    mRequestQueue.add(stringRequest);
}

Hàm này sử dụng các tiêu đề để chuyển một APIKEY và đặt một TAG cho yêu cầu hữu ích để hủy nó trước khi hoàn thành.

Hi vọng điêu nay co ich.


3

Điều này có thể giúp bạn ...

private void loggedInToMainPage(final String emailName, final String passwordName) {

    String tag_string_req = "req_login";
    StringRequest stringRequest = new StringRequest(Request.Method.POST, "http://localhost/index", new Response.Listener<String>() {
        @Override
        public void onResponse(String response) {
            Log.d(TAG, "Login Response: " + response.toString());
            try {
                JSONObject jsonObject = new JSONObject(response);
                Boolean error = jsonObject.getBoolean("error");
                if (!error) {

                    String uid = jsonObject.getString("uid");
                    JSONObject user = jsonObject.getJSONObject("user");
                    String email = user.getString("email");
                    String password = user.getString("password");


                    session.setLogin(true);
                    Intent intent = new Intent(getApplicationContext(), MainActivity.class);
                    startActivity(intent);
                    finish();
                    Toast.makeText(getApplicationContext(), "its ok", Toast.LENGTH_SHORT).show();
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }

        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError volleyError) {
            System.out.println("volley Error .................");
        }
    }) {
        @Override
        protected Map<String, String> getParams() throws AuthFailureError {
            Map<String, String> params = new HashMap<String, String>();
            params.put("tag", "login");
            params.put("email", emailName);
            params.put("password", passwordName);
            return params;
        }
    };


    MyApplication.getInstance().addToRequestQueue(stringRequest,tag_string_req);
}

3

Dành cho độc giả tương lai

Tôi thích làm việc với Volley . Để tiết kiệm thời gian phát triển, tôi đã cố gắng viết thư viện nhỏ tiện dụng Gloxey Netwok Manager để thiết lập Volley với dự án của mình. Nó bao gồm trình phân tích cú pháp JSON và các phương pháp khác giúp kiểm tra tính khả dụng của mạng.

Sử dụng ConnectionManager.classcác phương thức khác nhau cho yêu cầu Volley StringVolley JSON khả dụng. Bạn có thể thực hiện các yêu cầu GET, PUT, POST, DELETE có hoặc không có tiêu đề. Bạn có thể đọc toàn bộ tài liệu tại đây .

Chỉ cần đặt dòng này trong tệp gradle của bạn.

  dependencies { 

       compile 'io.gloxey.gnm:network-manager:1.0.1'
   }

Chuỗi vô-lê

Phương thức GET (không có tiêu đề)

    ConnectionManager.volleyStringRequest(context, isDialog, progressDialogView, requestURL, volleyResponseInterface);

Cách sử dụng?

     Configuration                Description

     Context                      Context 
     isDialog                     If true dialog will appear, otherwise not.
     progressView                 For custom progress view supply your progress view id and make isDialog true. otherwise pass null. 
     requestURL                   Pass your API URL.  
     volleyResponseInterface      Callback for response.  

Thí dụ

    ConnectionManager.volleyStringRequest(this, false, null, "url", new VolleyResponse() {
    @Override
    public void onResponse(String _response) {

        /**
         * Handle Response
         */
    }

    @Override
     public void onErrorResponse(VolleyError error) {

        /**
         * handle Volley Error
         */
    }

    @Override
    public void isNetwork(boolean connected) {

        /**
         * True if internet is connected otherwise false
         */
    }
});

Chuỗi vô-lê

Phương thức POST / PUT / DELETE (không có tiêu đề)

    ConnectionManager.volleyStringRequest(context, isDialog, progressDialogView, requestURL, requestMethod, params, volleyResponseInterface);

Thí dụ

Use Method : Request.Method.POST
             Request.Method.PUT
             Request.Method.DELETE

Your params : 

HashMap<String, String> params = new HashMap<>();
params.put("param 1", "value");
params.put("param 2", "value");

ConnectionManager.volleyStringRequest(this, true, null, "url", Request.Method.POST, params, new VolleyResponse() {
    @Override
    public void onResponse(String _response) {

        /**
         * Handle Response
         */
    }

    @Override
    public void onErrorResponse(VolleyError error) {

        /**
         * handle Volley Error
         */
    }

    @Override
    public void isNetwork(boolean connected) {

        /**
         * True if internet is connected otherwise false
         */
    }
});

Tặng kem

Gloxey JSON Parser

Hãy sử dụng trình phân tích cú pháp gloxey json để phân tích cú pháp api của bạn.

  YourModel yourModel = GloxeyJsonParser.getInstance().parse(stringResponse, YourModel.class);

Thí dụ

ConnectionManager.volleyStringRequest(this, false, null, "url", new VolleyResponse() {
    @Override
    public void onResponse(String _response) {

        /**
         * Handle Response
         */

         try {

          YourModel yourModel = GloxeyJsonParser.getInstance().parse(_response, YourModel.class);

            } catch (Exception e) {
                e.printStackTrace();
            }

    }

    @Override
     public void onErrorResponse(VolleyError error) {

        /**
         * handle Volley Error
         */
         if (error instanceof TimeoutError || error instanceof NoConnectionError) {

                showSnackBar(parentLayout, getString(R.string.internet_not_found), getString(R.string.retry), new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {

                     //handle retry button

                    }
                });

            } else if (error instanceof AuthFailureError) {
            } else if (error instanceof ServerError) {
            } else if (error instanceof NetworkError) {
            } else if (error instanceof ParseError) {
            }

    }

    @Override
    public void isNetwork(boolean connected) {

        /**
         * True if internet is connected otherwise false
         */
          if (!connected) {
                showSnackBar(parentLayout, getString(R.string.internet_not_found), getString(R.string.retry), new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        //Handle retry button
                    }
                });
    }
});


     public void showSnackBar(View view, String message) {
            Snackbar.make(view, message, Snackbar.LENGTH_LONG).show();
     }

     public void showSnackBar(View view, String message, String actionText, View.OnClickListener onClickListener) {
            Snackbar.make(view, message, Snackbar.LENGTH_LONG).setAction(actionText, onClickListener).show();
     }

Nhưng nó có hỗ trợ Method không. Hãy
David Kariuki

Có nó không, xin vui lòng xem để biết chi tiết. github.com/adnanbinmustafa/Gloxey-Network-Manager
Adnan Bin Mustafa

0

Để cung cấp POSTtham số, hãy gửi tham số của bạn như JSONObject trong hàm JsonObjectRequesttạo. Tham số thứ 3 chấp nhận một JSONObjectđược sử dụng trong phần thân Yêu cầu.

JSONObject paramJson = new JSONObject();

paramJson.put("key1", "value1");
paramJson.put("key2", "value2");


JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST,url,paramJson,
    new Response.Listener<JSONObject>() {
        @Override
        public void onResponse(JSONObject response) {

        }
    },
    new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {

        }
    });
requestQueue.add(jsonObjectRequest);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.