Volley使用singleton将访问令牌附加到evey请求

时间:2022-10-22 20:04:57

I am doing the following which perfectly works

我正在做以下完美的工作

    //else proceed with the checks
    JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(
            Request.Method.GET,
            checkauthurl,
            null,
            new Response.Listener<JSONObject>() {
                @Override
                public void onResponse(String response) { 
                         //do stuff here
                }
            },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                   // do stuff here
                }
            }) {
                @Override
                public Map<String, String> getHeaders() throws AuthFailureError {
                    HashMap<String, String> headers = new HashMap<String, String> ();
                    TokenService tokenservice = new TokenService(ctx);
                    String accesstoken = tokenservice.getToken(ApiHelper.ACCESS_TOKEN_SHARED_PREF);
                    headers.put("Authorization", "Bearer " + accesstoken);

                    return headers;
              }
    };

    // Access the RequestQueue through your singleton class.
    ApiSingleton strngle = new ApiSingleton(ctx);
    strngle.addToRequestQueue(jsonObjectRequest);

For every request, I have to add the request header. How can I set request headers directly in the singleton.

对于每个请求,我都要添加请求标头。如何直接在单例中设置请求标头。

This is my singleton

这是我的单身人士

private static ApiSingleton mInstance;
private RequestQueue mRequestQueue;
public static Context mCtx;
private ImageLoader mImageLoader;

public ApiSingleton(Context context) {
    mCtx = context;
    mRequestQueue = getRequestQueue();
    //do stuff
}

public RequestQueue getRequestQueue() {
    if (mRequestQueue == null) {
        // getApplicationContext() is key, it keeps you from leaking the
        // Activity or BroadcastReceiver if someone passes one in.
        mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext());
    }
    return mRequestQueue;
}

How do I avoid the above code duplication when attaching the bearer token in every request?

在每个请求中附加承载令牌时,如何避免上述代码重复?

3 个解决方案

#1


1  

public class CustomJsonRequest extends JsonRequest<Object>{
    public CustomJsonRequest(String url, String requestBody, Response.Listener<Object> listener,
                       Response.ErrorListener errorListener) {
        super(url, requestBody, listener, errorListener);
    }

    public CustomJsonRequest(int method, String url, String requestBody, Response.Listener<Object> listener,
                       Response.ErrorListener errorListener) {
        super(method, url, errorListener);
    }
    @Override
    protected Response<Object> parseNetworkResponse(NetworkResponse response) {
        return Response.success(Object, HttpHeaderParser.parseCacheHeaders(response));
    }

    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        Map<String, String> headers = new HashMap<String, String> ();
        TokenService tokenservice = new TokenService(ctx);
        String accesstoken = tokenservice.getToken(ApiHelper.ACCESS_TOKEN_SHARED_PREF);
        headers.put("Authorization", "Bearer " + accesstoken);
        return headers;
    }
}

You can extend JsonRequest class and override getHeaders() method. Pass instance of CustomJsonRequest object when you are adding volley requests in queue.

您可以扩展JsonRequest类并覆盖getHeaders()方法。在队列中添加排球请求时,传递CustomJsonRequest对象的实例。

VolleyUtils.getInstance().addToRequestQueue(customJsonRequest); 

#2


0  

  1. You can write a "Factory" with a method that takes your checkauthurl and ctx and returns you an instance of the JsonObjectRequest. Your factory could implement some logic for re-use of objects that have the same auth Url if that makes sense in your case.
  2. 您可以使用带有checkauthurl和ctx的方法编写“Factory”,并返回JsonObjectRequest的实例。如果在您的情况下有意义,您的工厂可以实现一些逻辑来重复使用具有相同auth Url的对象。

  3. You can sub-class JsonObjectRequest and provide your checkauthurl and ctx as a parameter to the constructor. Similarly, you can implement a scheme to re-use the objects
  4. 您可以将JsonObjectRequest子类化,并将checkauthurl和ctx作为参数提供给构造函数。同样,您可以实现一个方案来重用对象

The factory would be the suggested approach if you want Dependency Injection.

如果您想要依赖注入,那么工厂将是建议的方法。

I would recommend against pre-allocating the Token and using it in multiple requests. Tokens expire. If the TokenService is written well, it should know when tokens will expire and refresh as needed (if possible).

我建议不要预先分配令牌并在多个请求中使用它。代币过期。如果TokenService写得很好,它应该知道令牌何时到期并根据需要刷新(如果可能)。

#3


-1  

Make an AppController.java file and mention this file name as android:app in manifest tag.

制作一个AppController.java文件,并在清单标记中将此文件名称为android:app。

public class AppController extends Application {

    public static final String TAG = AppController.class.getSimpleName();
    private RequestQueue mRequestQueue;
    private static AppController mInstance;
    private ImageLoader mImageLoader;

    @Override
    public void onCreate() {
        super.onCreate();
        mInstance = this;
    }
    public static synchronized AppController getInstance() {
        return mInstance;
    }

    public RequestQueue getRequestQueue() {
        if (mRequestQueue == null) {
            mRequestQueue = Volley.newRequestQueue(getApplicationContext());
        }
        return mRequestQueue;
    }

    public ImageLoader getImageLoader() {
        getRequestQueue();
        if (mImageLoader == null) {
            mImageLoader = new ImageLoader(this.mRequestQueue, new LruBitmapCache());
        }
        return this.mImageLoader;
    }
    public <T> void addToRequestQueue(Request<T> req, String tag) {
        req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
        getRequestQueue().add(req);
    }
    public <T> void addToRequestQueue(Request<T> req) {
        req.setTag(TAG);
        getRequestQueue().add(req);
    }
    public void cancelPendingRequests(Object tag) {
        if (mRequestQueue != null) {
            mRequestQueue.cancelAll(tag);
        }
    }
}

Do the networking code

做网络代码

 StringRequest strReq = new StringRequest(Request.Method.POST, AppConfig.URL_BUYER_LOGIN, 
new Response.Listener<String>() {

                @Override
                public void onResponse(String response) {

                }
            }, new Response.ErrorListener() {

                @Override
                public void onErrorResponse(VolleyError error) {

                }
            }) {
                @Override
                protected Map<String, String> getParams() {

                }
            };
            // Adding request to request queue
            AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
        }

#1


1  

public class CustomJsonRequest extends JsonRequest<Object>{
    public CustomJsonRequest(String url, String requestBody, Response.Listener<Object> listener,
                       Response.ErrorListener errorListener) {
        super(url, requestBody, listener, errorListener);
    }

    public CustomJsonRequest(int method, String url, String requestBody, Response.Listener<Object> listener,
                       Response.ErrorListener errorListener) {
        super(method, url, errorListener);
    }
    @Override
    protected Response<Object> parseNetworkResponse(NetworkResponse response) {
        return Response.success(Object, HttpHeaderParser.parseCacheHeaders(response));
    }

    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        Map<String, String> headers = new HashMap<String, String> ();
        TokenService tokenservice = new TokenService(ctx);
        String accesstoken = tokenservice.getToken(ApiHelper.ACCESS_TOKEN_SHARED_PREF);
        headers.put("Authorization", "Bearer " + accesstoken);
        return headers;
    }
}

You can extend JsonRequest class and override getHeaders() method. Pass instance of CustomJsonRequest object when you are adding volley requests in queue.

您可以扩展JsonRequest类并覆盖getHeaders()方法。在队列中添加排球请求时,传递CustomJsonRequest对象的实例。

VolleyUtils.getInstance().addToRequestQueue(customJsonRequest); 

#2


0  

  1. You can write a "Factory" with a method that takes your checkauthurl and ctx and returns you an instance of the JsonObjectRequest. Your factory could implement some logic for re-use of objects that have the same auth Url if that makes sense in your case.
  2. 您可以使用带有checkauthurl和ctx的方法编写“Factory”,并返回JsonObjectRequest的实例。如果在您的情况下有意义,您的工厂可以实现一些逻辑来重复使用具有相同auth Url的对象。

  3. You can sub-class JsonObjectRequest and provide your checkauthurl and ctx as a parameter to the constructor. Similarly, you can implement a scheme to re-use the objects
  4. 您可以将JsonObjectRequest子类化,并将checkauthurl和ctx作为参数提供给构造函数。同样,您可以实现一个方案来重用对象

The factory would be the suggested approach if you want Dependency Injection.

如果您想要依赖注入,那么工厂将是建议的方法。

I would recommend against pre-allocating the Token and using it in multiple requests. Tokens expire. If the TokenService is written well, it should know when tokens will expire and refresh as needed (if possible).

我建议不要预先分配令牌并在多个请求中使用它。代币过期。如果TokenService写得很好,它应该知道令牌何时到期并根据需要刷新(如果可能)。

#3


-1  

Make an AppController.java file and mention this file name as android:app in manifest tag.

制作一个AppController.java文件,并在清单标记中将此文件名称为android:app。

public class AppController extends Application {

    public static final String TAG = AppController.class.getSimpleName();
    private RequestQueue mRequestQueue;
    private static AppController mInstance;
    private ImageLoader mImageLoader;

    @Override
    public void onCreate() {
        super.onCreate();
        mInstance = this;
    }
    public static synchronized AppController getInstance() {
        return mInstance;
    }

    public RequestQueue getRequestQueue() {
        if (mRequestQueue == null) {
            mRequestQueue = Volley.newRequestQueue(getApplicationContext());
        }
        return mRequestQueue;
    }

    public ImageLoader getImageLoader() {
        getRequestQueue();
        if (mImageLoader == null) {
            mImageLoader = new ImageLoader(this.mRequestQueue, new LruBitmapCache());
        }
        return this.mImageLoader;
    }
    public <T> void addToRequestQueue(Request<T> req, String tag) {
        req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
        getRequestQueue().add(req);
    }
    public <T> void addToRequestQueue(Request<T> req) {
        req.setTag(TAG);
        getRequestQueue().add(req);
    }
    public void cancelPendingRequests(Object tag) {
        if (mRequestQueue != null) {
            mRequestQueue.cancelAll(tag);
        }
    }
}

Do the networking code

做网络代码

 StringRequest strReq = new StringRequest(Request.Method.POST, AppConfig.URL_BUYER_LOGIN, 
new Response.Listener<String>() {

                @Override
                public void onResponse(String response) {

                }
            }, new Response.ErrorListener() {

                @Override
                public void onErrorResponse(VolleyError error) {

                }
            }) {
                @Override
                protected Map<String, String> getParams() {

                }
            };
            // Adding request to request queue
            AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
        }