改装电话正在加起来

时间:2016-09-12 19:27:26

标签: java android retrofit retrofit2 okhttp

我的应用程序中有一个用于注销用户会话的按钮,当它被点击时,改装会向localhost发送一个基本的POST请求,从技术上说它已被注销,但如果我再次点击注销按钮,则会发生以下情况: / p>

第一次:一个请求通过 第二次点击注销:同时注销2个请求 第三次点击注销:注销3个请求

依旧......

老实说,这种情况对我来说非常令人费解,是的,我使用okhttp拦截器和一些令牌管理进行改造。

注意: - (Tinydb是一个简单的共享偏好管理器)

以下代码:

ApiInterfacer.java - 这是我的api界面

@FormUrlEncoded
@POST("/api/token/logout")
Call<BasicResponse> LOG_OUT(@Field("guid") String guid);

ApiService.java - 我的Api服务创建者

public class ApiService {

public static final String baseurl = StaticVars.LOCALHOST;
public static OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
private static Retrofit.Builder retrofitbuilder = new Retrofit.Builder().baseUrl(baseurl).addConverterFactory(GsonConverterFactory.create());

public static <S>S createService(Class<S> serviceClass , Context context) // service class is the REST class , ex : GithubClient
{

    Retrofit retrofit = retrofitbuilder.build();
    httpClientBuilder.interceptors().add(new ApiTokenInterceptor(context));
    OkHttpClient client = httpClientBuilder.build();
    retrofitbuilder.client(client);
    return retrofit.create(serviceClass);

}

}

ApiTokenInterceptor.java

public class ApiTokenInterceptor implements Interceptor {

private final Context context;
public ApiTokenInterceptor(Context context){

    this.context = context;
}

@Override
public Response intercept(Chain chain) throws IOException {

    Log.i("INTERCEPT" , "FIRST " + chain.request().url());
    TinyDB db = new TinyDB(context);
    Request request = chain.request();
    Request modifiedReq = request;
    if(!db.getString("token").equals(""))
    {
        modifiedReq = request.newBuilder().addHeader("token" ,db.getString("token"))
                .build();
    }

    Response response = chain.proceed(modifiedReq);
    boolean unauthorized = response.code() == 401;
    Log.i("INTERCEPT" , "SECOND - LOGOUT - PROCEED " + modifiedReq.url() + " " + unauthorized);
    if(unauthorized){
        response.body().close();
        db.remove("token");
        String refreshToken = db.getString("refken");

        Request request1 = new Request.Builder()
                .url(StaticVars.LOCALHOST + "/api/token")
                .addHeader("refken" , refreshToken)
                .get()
                .build();
        OkHttpClient client = new OkHttpClient();
        Response response1 = client.newCall(request1).execute();
        String response_string = response1.body().string();
        Log.d("INTERCEPT" , "RESPONSE TOKEN STRING "  + response_string);
        try{
            JSONObject object = new JSONObject(response_string);
            String token = object.getString("token");
            //set token to db
            Log.d("TOKENB" , " "+token);
            db.putString("token" , token);
        }catch (JSONException e){
            e.printStackTrace();
            Log.d("INVALID RESPONSE" , " "+response_string);
            db.putString("token" , "placeholder");
            Log.i("INTERCEPT" , "AFINAL - LOGOUT - PROCEED " + modifiedReq.url());
            return response;
        }

        modifiedReq = request.newBuilder().addHeader("token" , db.getString("token"))
                .build();
        Log.i("INTERCEPT" , "BFINAL - LOGOUT - PROCEED " + modifiedReq.url());
        return chain.proceed(modifiedReq);
    }

    return response;

}


}

(使用).java - 使用按钮的onclicklistener

retro.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(final View v) {


            //call retrofit :)
            final ProgressDialog pd = new ProgressDialog(v.getContext());
            pd.setMessage("Loading...");
            pd.setCancelable(false);
            pd.setIndeterminate(true);
            pd.show();
            ApiInterfacer client = ApiService.createService(ApiInterfacer.class, v.getContext());
            Call<BasicResponse> call = client.LOG_OUT(db.getString("guid"));
            call.enqueue(new Callback<BasicResponse>() {
                @Override
                public void onResponse(Call<BasicResponse> call, Response<BasicResponse> response) {
                    Log.d("Response : string" , "" + response.message());
                    switch(response.code())
                    {
                        case 401:
                            Log.d("LOGOUT" , "Unauthorized : "+401);
                            break;
                        case 400:
                            Log.d("LOGOUT" , "Malformed Body : " + 400);
                            break;
                        case 404:
                            Log.d("LOGOUT" , "URL Not Found :" + 404);
                            break;
                        case 200:
                            Log.d("Message" ,""+ response.body().getMessage()+" "+response.body().getCode());
                            if(response.body().getCode().equals("LOGGEDOUT"))
                            {
                                db.remove("token");
                                db.remove("refken");
                                startActivity(new Intent(getActivity(), LoginActivity.class));
                                getActivity().finish();
                            }
                            break;
                        default:
                            BasicResponse resp = response.body();
                            if(resp==null)
                            {
                                Log.d("Error" , "Response is null : " + response.code());
                            }else {
                                Log.d("Code", "" + resp.getCode());
                                Log.d("Source", "" + resp.getSource());
                                Log.d("Message", "" + resp.getMessage());
                                Log.d("Error", "" + resp.getError());
                            }
                    }

                    if(!call.isCanceled()) {
                        Log.i("INTERCEPT" , "FORCE CANCEL");
                        call.cancel();
                    }
                    pd.cancel();
                }

                @Override
                public void onFailure(Call<BasicResponse> call, Throwable t) {
                    t.printStackTrace();
                    pd.cancel();
                    //page divert intent
                    Toast.makeText(v.getContext() , "Could not connect to server" , Toast.LENGTH_SHORT).show();
                    Log.d("FAIL" , ""+t.getMessage());

                    if(!call.isCanceled()) {
                        Log.i("INTERCEPT" , "FORCE CANCEL");
                        call.cancel();
                    }
                }
            });

        }
    });

日志: -

1st click : ( 0 * FIRST - Run at starting of interceptor ? interceptor not     running ?? )
09-13 00:40:04.657 29600-29600/some.example.okhttp I/INTERCEPT: FORCE CANCEL

2nd click : ( 1 * FIRST - Run at starting of interceptor )
09-13 00:41:45.156 29600-31375/some.example.okhttp I/INTERCEPT: FIRST http://192.168.2.2/api/token/logout
09-13 00:41:45.166 29600-31375/some.example.okhttp I/INTERCEPT: SECOND - LOGOUT - PROCEED http://192.168.2.2/api/token/logout false
09-13 00:41:45.217 29600-29600/some.example.okhttp I/INTERCEPT: FORCE CANCEL

3rd click: ( 3 * FIRST ) 
09-13 00:41:54.364 29600-31375/some.example.okhttp I/INTERCEPT: FIRST http://192.168.2.2/api/token/logout
09-13 00:41:54.364 29600-31375/some.example.okhttp I/INTERCEPT: FIRST http://192.168.2.2/api/token/logout
09-13 00:41:54.370 29600-31375/some.example.okhttp I/INTERCEPT: SECOND - LOGOUT - PROCEED http://192.168.2.2/api/token/logout true
09-13 00:41:54.382 29600-31375/some.example.okhttp I/INTERCEPT: BFINAL - LOGOUT - PROCEED http://192.168.2.2/api/token/logout
09-13 00:41:54.431 29600-31375/some.example.okhttp I/INTERCEPT: SECOND - LOGOUT - PROCEED http://192.168.2.2/api/token/logout true
09-13 00:41:54.454 29600-31375/some.example.okhttp I/INTERCEPT: BFINAL - LOGOUT - PROCEED http://192.168.2.2/api/token/logout
09-13 00:41:54.454 29600-31375/some.example.okhttp I/INTERCEPT: FIRST http://192.168.2.2/api/token/logout
09-13 00:41:54.466 29600-31375/some.example.okhttp I/INTERCEPT: SECOND - LOGOUT - PROCEED http://192.168.2.2/api/token/logout true
09-13 00:41:54.503 29600-31375/some.example.okhttp I/INTERCEPT: BFINAL - LOGOUT - PROCEED http://192.168.2.2/api/token/logout
09-13 00:41:54.695 29600-29600/some.example.okhttp I/INTERCEPT: FORCE CANCEL

4th click: ( 7 * FIRST )
09-13 00:42:57.726 29600-32408/some.example.okhttp I/INTERCEPT: FIRST http://192.168.2.2/api/token/logout
09-13 00:42:57.726 29600-32408/some.example.okhttp I/INTERCEPT: FIRST http://192.168.2.2/api/token/logout
09-13 00:42:57.726 29600-32408/some.example.okhttp I/INTERCEPT: FIRST http://192.168.2.2/api/token/logout
09-13 00:42:57.731 29600-32408/some.example.okhttp I/INTERCEPT: SECOND - LOGOUT - PROCEED http://192.168.2.2/api/token/logout true
09-13 00:42:57.740 29600-32408/some.example.okhttp I/INTERCEPT: BFINAL - LOGOUT - PROCEED http://192.168.2.2/api/token/logout
09-13 00:42:57.779 29600-32408/some.example.okhttp I/INTERCEPT: SECOND - LOGOUT - PROCEED http://192.168.2.2/api/token/logout true
09-13 00:42:57.819 29600-32408/some.example.okhttp I/INTERCEPT: BFINAL - LOGOUT - PROCEED http://192.168.2.2/api/token/logout
09-13 00:42:57.819 29600-32408/some.example.okhttp I/INTERCEPT: FIRST http://192.168.2.2/api/token/logout
09-13 00:42:57.831 29600-32408/some.example.okhttp I/INTERCEPT: SECOND - LOGOUT - PROCEED http://192.168.2.2/api/token/logout true
09-13 00:42:57.865 29600-32408/some.example.okhttp I/INTERCEPT: BFINAL - LOGOUT - PROCEED http://192.168.2.2/api/token/logout
09-13 00:42:57.892 29600-32408/some.example.okhttp I/INTERCEPT: SECOND - LOGOUT - PROCEED http://192.168.2.2/api/token/logout true
09-13 00:42:57.942 29600-32408/some.example.okhttp I/INTERCEPT: BFINAL - LOGOUT - PROCEED http://192.168.2.2/api/token/logout
09-13 00:42:57.942 29600-32408/some.example.okhttp I/INTERCEPT: FIRST http://192.168.2.2/api/token/logout
09-13 00:42:57.942 29600-32408/some.example.okhttp I/INTERCEPT: FIRST http://192.168.2.2/api/token/logout
09-13 00:42:57.968 29600-32408/some.example.okhttp I/INTERCEPT: SECOND - LOGOUT - PROCEED http://192.168.2.2/api/token/logout true
09-13 00:42:58.006 29600-32408/some.example.okhttp I/INTERCEPT: BFINAL - LOGOUT - PROCEED http://192.168.2.2/api/token/logout
09-13 00:42:58.029 29600-32408/some.example.okhttp I/INTERCEPT: SECOND - LOGOUT - PROCEED http://192.168.2.2/api/token/logout true
09-13 00:42:58.053 29600-32408/some.example.okhttp I/INTERCEPT: BFINAL - LOGOUT - PROCEED http://192.168.2.2/api/token/logout
09-13 00:42:58.053 29600-32408/some.example.okhttp I/INTERCEPT: FIRST http://192.168.2.2/api/token/logout
09-13 00:42:58.086 29600-32408/some.example.okhttp I/INTERCEPT: SECOND - LOGOUT - PROCEED http://192.168.2.2/api/token/logout true
09-13 00:42:58.152 29600-32408/some.example.okhttp I/INTERCEPT: BFINAL - LOGOUT - PROCEED http://192.168.2.2/api/token/logout
09-13 00:42:58.245 29600-29600/some.example.okhttp I/INTERCEPT: FORCE CANCEL

1 个答案:

答案 0 :(得分:1)

每次创建Retrofit服务时,请再次安装您的服务,这可能会导致问题。

尝试制作一个返回factory服务的singleton

   private static AmazonServices amazonServices = null;
    private static PurpleServices purpleServices = null;

    static OkHttpClient.Builder httpClient = getUnsafeOkHttpClient();

    private static Retrofit.Builder builder = new Retrofit.Builder();

    public static <S> S createService(Class<S> serviceClass) {

        S mAPI = null;
        if (serviceClass.getSimpleName().equals("PurpleService")) {
            if (purpleServices == null) {
                purpleServices = (PurpleServices) createPurpleAPI(serviceClass);
            }
            mAPI = (S) purpleServices;
        } else if (serviceClass.getSimpleName().equals("AmazonServices")) {
            if (amazonServices == null) {
                amazonServices = (AmazonServices) createAmazonAPI(serviceClass);
            }
            mAPI = (S) amazonServices;
        }
        return mAPI;
    }

你这样称呼它:

private AmazonServices amazonServices = RetrofitCreator.createService(AmazonServices.class);