Retrofit2 перехватчик, используя токен только в определенных методах - PullRequest
0 голосов
/ 20 марта 2019

Я хочу использовать authorization в Retrofit2. Я выбрал interceptor способ, потому что почти все методы требуют authorization, кроме одного, где я получаю токен для дальнейшего использования с другими методами.

Мой вопрос: Как мне этого добиться?

Я храню свой токен доступа в SharedPreferences. Моей первой идеей было: « Я могу получить его в своем классе RetrofitClient, и в зависимости от того, является ли токен нулевым или имеет значение, создайте подходящий Retrofit экземпляр » (с добавлением или без добавления .client() к нему.

К сожалению, это не так просто, потому что Context необходим для получения настроек.

Я не знаю, как передать его в RetrofitClient класс или как добраться до него внутри.

Вот мой RetrofitClient класс:

public class RetrofitClient {

    public static final String BASE_URL = "http://localhost";
    public static Retrofit retrofit = null;

    private RetrofitClient() {
        retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                //.client(getRequestHeader())
                .build();
    }

    /*OkHttpClient client = new OkHttpClient.Builder().addInterceptor(new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request newRequest = chain.request().newBuilder()
                    .addHeader("Authorization", "Bearer" + )
        }
    })*/

    public static synchronized Retrofit getInstance() {
        if (retrofit == null) {

            retrofit = new Retrofit.Builder().baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create()).build();
        }
        return retrofit;
    }

    public Api getApi() {
        return retrofit.create(Api.class);
    }
}

Мой getRequestHeader() - предыдущий метод, в котором я устанавливал тайм-аут.

Я хочу создать экземпляр следующим образом:

private RetrofitClient() {
            tokenService.token = null;
            tokenService.readToken(ApplicationContext.getInstance());


            if (tokenService.token == null) {
                retrofit = new Retrofit.Builder()
                        .baseUrl(BASE_URL)
                        .addConverterFactory(GsonConverterFactory.create())
                        .build();
            } else {
                retrofit = new Retrofit.Builder()
                        .baseUrl(BASE_URL)
                        .addConverterFactory(GsonConverterFactory.create())
                        .client(client) //I have interceptor here with access token
                        .build();
            }
        }

А потом:
RetrofitClient.getInstance().create(Api.class).getToken() // получение токена
RetrofitClient.getInstance().create(Api.class).someMethod() // когда я получаю токен

Это хороший подход?

Ответы [ 3 ]

1 голос
/ 20 марта 2019

Вы можете использовать контекст приложения, который доступен, пока ваше приложение работает. Получить его из вашего класса приложения:

public class MyApp extends Application {
    private static MyApp instance;
    @Override
    public void onCreate() {
    super.onCreate();
    instance = this;
    //other code
}
public static MyApp getInstance() {
    return instance;
}

А затем просто используйте MyApp.getInstance(), чтобы получить контекст, где вам нужно. С этим подходом вы можете достичь того, о чем вы думали раньше, и получить SharedPreferences в RetrofitClient классе.

Не забудьте добавить класс приложения в манифест.

UPDATE: Вы создаете свой экземпляр модификации только один раз, поэтому, если вы создадите его, когда у вас будет токен - вы всегда будете использовать его, пока приложение живо. Я думаю, хорошая практика - проверять токен в вашем перехватчике. Примерно так:

new Interceptor() {
        @Override
        public Response intercept(@NonNull Chain chain) throws IOException {
            Request request = chain.request();
            if (tokenService.token == null) {
                return chain.proceed(request);
            } else {
                return chain.proceed(request.newBuilder().addHeader("Authorization", "Bearer" + tokenService.token).build());
            }
        }
    }

Кроме того, я не знаю, как работает ваш токен-сервис. Но имейте в виду, что лучше всего всегда проверять общие настройки для токена, если вы очищаете его там при выходе из системы. Потому что ваш tokenService может хранить строку токена, даже если она очищена в общих настройках.

0 голосов
/ 20 марта 2019

Вы можете сделать следующим образом:

Сначала создайте класс предпочтений с единичным экземпляром

Preferences

public class Preferences {

    public static Preferences INSTANCE;
    private final String PREFERENCE_FILE = "my_preferences";
    public final String PREF_TOKEN = "pref_user_token";
    private SharedPreferences mPrefs;
    private SharedPreferences.Editor mEdit;

    private Preferences() {
        Application app = MyApplicationClass.getInstance();
        mPrefs = app.getSharedPreferences(PREFERENCE_FILE, Context.MODE_PRIVATE);
        mEdit = mPrefs.edit();
    }

    // Returns singleton instance
    public static Preferences getInstance() {
        if (INSTANCE == null)
            INSTANCE = new Preferences();
        return INSTANCE;
    }

    public String getToken() {
        return Preferences.getInstance().mPrefs.getString(PREF_TOKEN, "");
    }

    public void saveToken(String value) {
        mEdit.putString(PREF_TOKEN, value);
        mEdit.apply();
    }

}

Затем измените класс RetrofitClient, как показано ниже:

RetrofitClient

public class RetrofitClient {

    public static final String BASE_URL = "http://localhost";
    public static Retrofit retrofit = null;

    private RetrofitClient() {
        retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .client(mClient)
                .build();
    }

    OkHttpClient mClient = new OkHttpClient.Builder().addInterceptor(new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request newRequest = chain.request().newBuilder()
                    .addHeader("Authorization", "Bearer" + Preferences.getInstance().getToken())
        }
    })

    public static synchronized Retrofit getInstance() {
        if (retrofit == null) {

            retrofit = new Retrofit.Builder().baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create()).build();
        }
        return retrofit;
    }

    public Api getApi() {
        return retrofit.create(Api.class);
    }
}
0 голосов
/ 20 марта 2019

Просто добавьте SharedPreferences в качестве параметра конструктора в RetrofitClient или другой в зависимости от ситуации

...