공통 저장소를 사용하는 두 개의 조각이 있습니다.RxJava 및 switchIfEmpty()를 사용한 저장소 데이터 캐시 관리
이 저장소에 대한 캐시 관리 시스템을 구현하려고합니다.
아이디어는 다음과 같습니다 조각 중 하나가로드 , 그것은 getData()
메소드를 호출,이 방법은 getDataFromNetwork()
을 사용하여 원격 JSON API에 대한 네트워크 호출을하기 위해선, 결과를 얻을 수 및 (A List<Aqicn>
로 캐시에 넣어 내 코드에서 변수 data
).
다음 조각이로드됩니다. 60 초가 지난 후 네트워크 호출이 없으면 getDataFromMemory()
을 사용하여 데이터가 내 데이터 목록의 캐시에서 직접 가져옵니다.
RxJava Observable.switchIfEmpty()
은 Observable (내 ArrayList)이 비어 있는지 여부를 확인하고 올바른 방법을 호출하는 데 사용됩니다.
나는 이것을 데뷔하는 방법을 알지 못했기 때문에 단지 메인 레이아웃에 버튼을 넣었습니다. 앱을 실행하면 첫 번째 조각이 자동으로로드되고 getData()
이 처음으로 호출됩니다. 이 버튼을 누르면 두 번째 조각이로드되고 getData()
두 번째 조각이로드됩니다.
60 초 전에이 버튼을 누르지 않으면 JSON API에 대한 네트워크 호출이 없어야하지만 ... 하나 있는데 항상 두 번째 네트워크 호출이 발생하고 캐시 데이터가 사용되지 않습니다. 내 코드에 무슨 문제가 있습니까?
public class CommonRepository implements Repository {
private static final String TAG = CommonRepository.class.getSimpleName();
private long timestamp;
private static final long STALE_MS = 60 * 1000; // Data is stale after 60 seconds
private PollutionApiService pollutionApiService;
private ArrayList<Aqicn> data;
public CommonRepository(PollutionApiService pollutionApiService) {
this.pollutionApiService = pollutionApiService;
this.timestamp = System.currentTimeMillis();
data = new ArrayList<>();
}
@Override
public Observable<Aqicn> getDataFromNetwork(String city, String authToken) {
Observable<Aqicn> aqicn = pollutionApiService.getPollutionObservable(city, authToken)
.doOnNext(new Action1<Aqicn>() {
@Override
public void call(Aqicn aqicn) {
data.add(aqicn);
}
});
return aqicn;
}
private boolean isUpToDate() {
return System.currentTimeMillis() - timestamp < STALE_MS;
}
@Override
public Observable<Aqicn> getDataFromMemory() {
if (isUpToDate()) {
return Observable.from(data);
} else {
timestamp = System.currentTimeMillis();
data.clear();
return Observable.empty();
}
}
@Override
public Observable<Aqicn> getData(String city, String authToken) {
return getDataFromMemory().switchIfEmpty(getDataFromNetwork(city, authToken));
}
}
======= 편집 : 최소 ===========
public class CommonRepository implements Repository {
private PollutionApiService pollutionApiService;
private static Observable<Aqicn> cachedData = null;
public CommonRepository(PollutionApiService pollutionApiService) {
this.pollutionApiService = pollutionApiService;
}
@Override
public Observable<Aqicn> getDataFromNetwork(String city, String authToken) {
Observable<Aqicn> aqicn = pollutionApiService.getPollutionObservable(city, authToken);
cachedData = aqicn;
return aqicn;
}
@Override
public Observable<Aqicn> getData(String city, String authToken) {
if(cachedData == null) {
return getDataFromNetwork(city, authToken);
}
return cachedData;
}
}
에 내 코드를 단순화 그리고 바로 깨달았다 상관없이 내가 네트워크 호출이 이루어집니다 return cachedData
을 할 때 나는
===== 편집은 문제 발견하지만 해결책은 ==========
발견 ...,하고있어 0것은 내 생성자 내 pollutionApiService 이니셜입니다. json으로 요청이 사용 단검과는 관찰 가능한을 반환
public interface PollutionApiService {
@GET("feed/{city}/")
Observable<Aqicn> getPollutionObservable(@Path("city") String city, @Query("token") String token);
}
나는이 모든 세부 사항에서 작동하는 방법을 알고하지 않습니다하지만이 같은 interprate. Dagger는 Observable 인 PollutionApiService 공급자를 만듭니다. 내가 할 때 return cachedData
Observable Observable이 가입되어 네트워크 콜이 완료되었지만 어떻게 해결할 것인가 전혀 모른다. 사실 내가 return cachedData
네트워크 통화가있을 때마다입니다.
당신이 주어진 PARAMS 모든 요청을 캐시 하시겠습니까? 첫 번째 getData를 city : 'Hamburg'및 auth : X로 호출 한 후 'Berlin', 'X'두 요청을 모두 60 초 동안 캐시해야합니까?현재 구현에서는 각 요청에 대해 캐시에 요소를 추가하기 만하면됩니다. –
두 매개 변수 모두 매개 변수가 동일합니다. – Laurent