2015-10-15 108 views
1

所以,有點上下文。我使用Dagger2,Retrofit和RxAndroid,並使用MVP架構構建我的應用程序。Dagger2單身註釋不起作用

現在,我所做的只是向API發出網絡請求,並在我的主要活動開始後立即檢索一些信息。我試圖通過配置更改來堅持我的演示者,以避免每次旋轉屏幕時都發出新的http請求。

MainActivity.java

public class MainActivity extends AppCompatActivity implements ForecastView { 


@Inject 
Presenter forecastPresenter; 

private TextView text; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    text = (TextView) findViewById(R.id.weather); 
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 
    setSupportActionBar(toolbar); 
    initializeDependencies(); 
    initializePresenter(); 
} 

private void initializeDependencies() { 
    DaggerWeatherApiComponent.builder() 
      .build().inject(this); 
} 

private void initializePresenter() { 
    forecastPresenter.attachView(this); 
    forecastPresenter.onCreate(); 

} 

WeatherApiComponent.java

@Component(modules = {EndpointsModule.class}) 
@Singleton 
public interface WeatherApiComponent { 
    void inject(MainActivity context); 
} 

EndpointsModule.java

@Module @Singleton 
public class EndpointsModule { 

    @Provides 
    @Singleton 
    WeatherEndpoints provideEndpoints() { 
     Retrofit retrofit = new Retrofit.Builder() 
       .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 
       .addConverterFactory(GsonConverterFactory.create()) 
       .client(new OkHttpClient()) 
       .baseUrl("http://api.openweathermap.org/data/2.5/") 
       .build(); 
     return retrofit.create(WeatherEndpoints.class); 
    } 

    @Provides 
    @Singleton 
    Repository providesRepository(RestRepository repository) { 
     return repository; 
    } 

    @Provides 
    @Singleton 
    Presenter providesPresenter(ForecastPresenter presenter) { 
     return presenter; 
    } 
} 

RestRespository

public class RestRepository implements Repository { 
    private WeatherEndpoints endpoints; 
    static final String API_KEY = "xxxxxxxxxxxxxxxxxxxxx"; 

    @Inject 
    public RestRepository(WeatherEndpoints endpoints) { 
     this.endpoints = endpoints; 
    } 

    public Observable<Current> getCurrentWeather(String cityName) { 
     return endpoints.getCurrent(cityName, API_KEY); 
    } 

    public Observable<com.feresr.rxweather.models.List> getForecast(String cityName) { 
     return endpoints.getForecast(cityName, API_KEY).flatMap(new Func1<FiveDays, Observable<com.feresr.rxweather.models.List>>() { 
      @Override 
      public Observable<com.feresr.rxweather.models.List> call(FiveDays fiveDays) { 
       return Observable.from(fiveDays.getList()); 
      } 
     }); 
    } 

}

ForecastPresenter.java

public class ForecastPresenter implements Presenter { 
private GetForecastUseCase useCase; 
private Subscription forecastSubscription; 
private ArrayList<List> lists; 
private ForecastView forecastView; 

@Inject 
public ForecastPresenter(GetForecastUseCase forecastUseCase) { 
    this.useCase = forecastUseCase; 
    lists = new ArrayList<>(); 
} 

@Override 
public void onStop() { 
    if (forecastSubscription.isUnsubscribed()) { 
     forecastSubscription.unsubscribe(); 
    } 
} 

@Override 
public void attachView(View v) { 
    forecastView = (ForecastView) v; 
} 


@Override 
public void onCreate() { 
    if (lists.isEmpty()) { 
     forecastSubscription = useCase.execute().subscribe(new Action1<List>() { 
      @Override 
      public void call(List list) { 
       lists.add(list); 
       forecastView.addForecast(list.getWeather().get(0).getMain()); 
      } 
     }); 
    } else { 
     forecastView.addForecast(lists.get(0).toString()); 
    } 
} 

這個類(主持人)構造函數保持自稱爲我轉動我的活性。我用@Singleton註釋了大部分課程。我不知道還有什麼要做。

編輯:請注意,我還沒有進入匕首範圍,現在我不在乎,如果這個單身節目主持人只要我的應用程序生活。我稍後會解決這個問題。

回答

4

看起來您每次調用MainActivity.onCreate(Bundle)時都會重新創建Dagger組件,並且在旋轉屏幕時該活動會重新生成。

與其他示波器一樣,@Singleton表示對於組件的生命週期,對於JVM的生命週期不會有一個對象的實例。您通常必須確保自己只有一個@Singleton組件實例,通常通過將其保存在您的Application的字段中。

+1

完全正確! –

+0

哦!,所以...爲什麼我們打擾使用@singleton註釋標註組件和模塊? – feresr

+1

將一個範圍註釋添加到'@Provision'方法意味着該方法將在安裝到其中的組件的一個實例中最多被調用一次。 否則,即使在一個組件實例中,每次調用Provider的get()方法時,都會再次調用@ @提供方法。每一個'@注入'RestRepository'的類都會得到一個新的實例。 – netdpb

1

您在這裏創建一個新的匕首組件每次:

private void initializeDependencies() { 
    DaggerWeatherApiComponent.builder() 
      .build().inject(this); 
} 

一個範圍依賴存在作爲一個實例,每個組件。

如果您創建了一個新組件,它將擁有自己的作用域,並且它將創建自己的實例。

您應該投資Mortar範圍來保留您的組件,或者您的Application實例中應該有某種「緩存」。