2017-03-27 19 views
6

Tôi tự hỏi nếu có một cách để Dagger biết rằng nó sẽ tạo lại một đối tượng khi có dữ liệu mới.Dagger + Trang bị thêm. Thêm tiêu đề auth tại thời gian chạy

Ví dụ tôi đang nói đến là với tiêu đề yêu cầu tôi có để trang bị thêm. Tại một số thời điểm (khi người dùng đăng nhập), tôi nhận được một mã thông báo mà tôi cần phải thêm vào các tiêu đề của trang bị thêm để thực hiện các yêu cầu đã được xác thực. Vấn đề là, tôi còn lại với cùng một phiên bản unauthenticated trang bị thêm. Đây là mã tiêm của tôi:

@Provides 
    @Singleton 
    OkHttpClient provideOkHttpClient(Cache cache) { 
     HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); 
     interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); 
     OkHttpClient client = new OkHttpClient.Builder() 
       .addInterceptor(interceptor) 
       .cache(cache).build(); 
     client 
       .newBuilder() 
       .addInterceptor(
        chain -> { 
         Request original = chain.request(); 
         Request.Builder requestBuilder = original.newBuilder() 
           .addHeader("Accept", "Application/JSON"); 
         Request request = requestBuilder.build(); 
         return chain.proceed(request); 
        }).build(); 
     return client; 
    } 

    @Provides 
    @Singleton 
    Retrofit provideRetrofit(Gson gson, OkHttpClient okHttpClient) { 
     Retrofit retrofit = new Retrofit.Builder() 
       .addConverterFactory(GsonConverterFactory.create(gson)) 
       .addCallAdapterFactory(RxErrorHandlingCallAdapterFactory.create()) 
       .baseUrl(mBaseUrl) 
       .client(okHttpClient) 
       .build(); 
     return retrofit; 
} 

@Provides 
    @Singleton 
    public NetworkService providesNetworkService(Retrofit retrofit) { 
     return retrofit.create(NetworkService.class); 
    } 

Bất kỳ ý tưởng nào về cách thực hiện công việc này?

Trả lời

3

Hãy xem xét sử dụng the approach đề cập bởi @oldergod vì nó là cách "chính thức" và tốt hơn nhiều, trong khi các phương pháp đề cập dưới đây là không khuyên, họ có thể được coi là cách giải quyết.


Bạn có một vài tùy chọn.

  1. Ngay khi bạn nhận được dấu hiệu, bạn có null ra các thành phần mà cung cấp cho bạn những ví dụ Retrofit, tạo ra một thành phần mới và yêu cầu một Retrofit dụ mới, sẽ được khởi tạo với cần thiết okhttp dụ.
  2. Một thẻ nhanh và xấu - Lưu mã thông báo trong SharedPreferences, tạo tiêu đề okHttp, sẽ áp dụng đọc mã thông báo từ SharedPreferences. Nếu không có - gửi tiêu đề không có mã thông báo.
  3. giải pháp Thậm chí xấu xí - tuyên bố một lĩnh vực static volatile String, và làm điều tương tự như ở bước 2.

Tại sao lựa chọn thứ hai là xấu? Bởi vì trên mỗi yêu cầu bạn sẽ bỏ phiếu cho thẻ SD và lấy dữ liệu từ đó.

+0

Đối với tùy chọn 1. Làm cách nào để yêu cầu một phiên bản trang bị mới? – AIntel

+0

Giả sử bạn có một 'FooComponent fooCompomnent', cung cấp cá thể' Retrofit'. Bây giờ bạn 'null' ra thành phần đó và tạo một' FooComponent' mới. – azizbekian

+0

Đánh dấu câu trả lời của bạn là chính xác, vì tôi hiểu và xem giải pháp của bạn hoạt động như thế nào. Vấn đề với thiết lập của tôi là tôi xây dựng tiêm trang bị thêm cho người trình bày của tôi mà chính nó được tiêm trong quan điểm của tôi. Và tôi làm điều này trên quan điểm của tôi một số trong đó có các thành phần riêng của họ mà phụ thuộc vào thành phần mạng của tôi. Tôi đã hy vọng cho một số giải pháp ma thuật mà bằng cách nào đó sẽ buộc người thuyết trình của tôi được tái xuất hiện trên tất cả các quan điểm của tôi. – AIntel

8

Cá nhân tôi đã tạo một okhttp3.Interceptor làm điều đó cho tôi, mà tôi cập nhật khi tôi có mã thông báo bắt buộc. Có vẻ như:

@Singleton 
public class MyServiceInterceptor implements Interceptor { 
    private String sessionToken; 

    @Inject public MyServiceInterceptor() { 
    } 

    public void setSessionToken(String sessionToken) { 
    this.sessionToken = sessionToken; 
    } 

    @Override public Response intercept(Chain chain) throws IOException { 
    Request request = chain.request(); 

    Request.Builder requestBuilder = request.newBuilder(); 

    if (request.header(NO_AUTH_HEADER_KEY) == null) { 
     // needs credentials 
     if (sessionToken == null) { 
     throw new RuntimeException("Session token should be defined for auth apis"); 
     } else { 
     requestBuilder.addHeader("Cookie", sessionToken); 
     } 
    } 

    return chain.proceed(requestBuilder.build()); 
    } 
} 

Trong thành phần dao găm tương ứng, tôi vạch ra bộ chặn này để tôi có thể đặt sessionToken khi cần.

Đó là một số nội dung mà Jake đã nói về bài nói chuyện của mình Making Retrofit Work For You.

+0

Có ví dụ nào về điều này không. –

Các vấn đề liên quan