2016-08-25 54 views
0

我想更新網絡請求中的訪問令牌。但使用Dagger和Retrofit時有一些困難。訪問令牌更新時的更新請求標頭更新Dagger和Retrofit

對不起,我的英語不是很好,所以給你一個例子可能是從無到有多clear.Starting,我的想法是這樣的:

提供保存在共享偏好的訪問令牌

@Provides 
@ForOauth 
Preference<String> provideAccessToken(RxSharedPreferences prefs) { 
    return prefs.getString(PrefsUtils.KEY_ACCESS_TOKEN); 
} 

使用訪問令牌來創建一個攔截器,並加入到okhttp客戶

@Provides 
@Singleton 
@Named("Cached") 
public OkHttpClient provideOkHttpClientWithCache(Application application, @ForOauth OauthInterceptor oauthInterceptor) { 
     ... 
    builder.addInterceptor(oauthInterceptor); 
     ... 
} 

,我通過它的構造

@Inject 
public OauthInterceptor(@ForOauth Preference<String> accessToken) { 
    this.accessToken = accessToken; 
    Timber.tag("OauthInterceptor"); 
} 

提供OauthInterceptor實例,但導致okhttp客戶是單身,也不會在首選項updates.An另一種方式改變時訪問令牌我認爲可能的作用是使用像@ForOauth之類的自定義範圍,但它只是一個粗略的草圖...

順便說一句,我有另一種想法是這樣的:

intercept()方法中的首選項獲取訪問令牌,所以每次我都可以擁有包含最新訪問令牌的請求標頭。

@Override 
public Response intercept(Chain chain) throws IOException { 
    Request.Builder builder = chain.request().newBuilder(); 
    if (accessToken.isSet()) { 
     // Preference<String> accessToken 
     builder.header("Authorization", ACCESS_TYPE + accessToken.get()); 
    } else { 
     builder.header("Authorization", "Bearer xxxxxx"); 
    } 
    return chain.proceed(builder.build()); 
} 

但我還沒有真正嘗試過這樣的想法,我認爲這是不對的

我不知道我是否有每次創建新的okhttp客戶端實例或我可以更新訪問令牌然後okhttp客戶端單身人士可以刷新其攔截器...

所以,你可以給我一些建議,或一個簡單的工作示例。

在此先感謝

回答

0

Hmmmm,我已經做了很多次,從來沒有與訪問令牌刷新沒有做它的方式下來鏈OkHttp發現任何問題。以下是我在應用程序使用的典型設置:

@Provides @Singleton 
SharedPreferences providePreferences(Context ctx) { 
    return new SharedPreferences(ctx); 
} 

@Provides @Singleton 
HttpLoggingInterceptor provideLoggingInterceptor(){ 
    return new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY); 
} 

@Provides @Singleton 
OkHttpClient provideClient(HttpLoggingInterceptor interceptor, SharedPreferences prefs){ 
    return new OkHttpClient.Builder() 
      .addNetworkInterceptor(chain -> { 
       // Add Auth Header 
       String token = prefs.accessToken().get(); 
       if(token == null) token = ""; 

       Request request = chain.request().newBuilder().addHeader("Authorization", token).build(); 
       return chain.proceed(request); 
      }) 
      .addInterceptor(interceptor) 
      .build(); 
} 

@Provides @Singleton 
Retrofit provideRetrofit(@ApiUrl String url, OkHttpClient client){ 
    return new Retrofit.Builder() 
      .baseUrl(url) 
      .client(client) 
      .addConverterFactory(LoganSquareConverterFactory.create()) 
      .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 
      .build(); 
} 

SharedPreferences只是我摘錄了一些RxSharedPreferences邏輯成爲階級。也可以只用@Inject它在應用程序中的任何位置,這很好。以下是該課程的簡單版本,僅供參考:

public class SharedPreferences { 
    // Constants and variables 
    private static final String PREFERENCE_FILENAME = BuildConfig.APPLICATION_ID + ".prefs"; 
    private static final String PREF_ACCESS_TOKEN= "pref_access_token"; 

    private RxSharedPreferences mRxSharedPrefs; 

    // Constructor 
    public SharedPreferences(Context context) { 
     mRxSharedPrefs = RxSharedPreferences.create(context.getSharedPreferences(PREFERENCE_FILENAME, Context.MODE_PRIVATE)); 
    } 

    // Helper methods 
    public Preference<String> accessToken() { return mRxSharedPrefs.getString(PREF_ACCESS_TOKEN, ""); } 

    public void logout() { accessToken().delete(); } 
} 
+0

這真的有用嗎?如果我將改造注入到我的活動中,讓我們假設,併發出一個請求,返回一個存儲到共享首選項中的authtoken。這是否意味着我將能夠使用相同的改造實例進行認證請求?我想不會。需要有一種方法來重新進行或更新改造。 – AIntel

+0

每次發出HTTP請求時,閱讀偏好似乎都不是最好的主意。 –

+0

@lalongooo,那麼,你如何解決呢? – Davidea