Skip to content
This repository has been archived by the owner on Jan 14, 2018. It is now read-only.

Commit

Permalink
Refactor of core of SpiceService. Issue #245.
Browse files Browse the repository at this point in the history
  • Loading branch information
stephanenicolas committed Jan 14, 2014
1 parent ebeffaf commit 3227f2b
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ public void trimToSize(int maxSize) {
K key;
V value;
synchronized (this) {
if (size < 0 || (map.isEmpty() && size != 0)) {
if (size < 0 || map.isEmpty() && size != 0) {
throw new IllegalStateException(getClass().getName() + ".sizeOf() is reporting inconsistent results!");
}

Expand Down Expand Up @@ -324,7 +324,7 @@ public final synchronized Map<K, V> snapshot() {
@Override
public final synchronized String toString() {
int accesses = hitCount + missCount;
int hitPercent = accesses != 0 ? (MAX_PERCENT * hitCount / accesses) : 0;
int hitPercent = accesses != 0 ? MAX_PERCENT * hitCount / accesses : 0;
return String.format("LruCache[maxSize=%d,hits=%d,misses=%d,hitRate=%d%%]", maxSize, hitCount, missCount, hitPercent);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ public class RequestProcessorTest extends AndroidTestCase {
private MockNetworkStateChecker networkStateChecker;
private DefaultRequestListenerNotifier progressReporter;
private SpiceServiceListenerNotifier spiceServiceListenerNotifier;
private RequestProgressManager mockRequestProgressManager;
private RequestRunner mockRequestRunner;

@Override
protected void setUp() throws Exception {
Expand All @@ -78,10 +80,12 @@ public void requestsInProgress() {
networkStateChecker = new MockNetworkStateChecker();
progressReporter = new DefaultRequestListenerNotifier();
spiceServiceListenerNotifier = new SpiceServiceListenerNotifier();
requestProcessorUnderTest = new RequestProcessor(getContext(), mockCacheManager, executorService, requestProcessorListener, networkStateChecker, progressReporter,
spiceServiceListenerNotifier);
mockRequestProgressManager = new RequestProgressManager(requestProcessorListener, progressReporter, spiceServiceListenerNotifier);
mockRequestRunner = new RequestRunner(getContext(), mockCacheManager, executorService, mockRequestProgressManager, networkStateChecker);

requestProcessorUnderTest = new RequestProcessor(mockCacheManager, mockRequestProgressManager, mockRequestRunner);
}

@Override
protected void tearDown() throws Exception {
requestProcessorUnderTest.shouldStop();
Expand Down Expand Up @@ -121,8 +125,8 @@ public void testObservers_with_AddRequest_when_cache_is_not_used() throws Interr
CachedSpiceRequestStub<String> stubRequest = createSuccessfulRequest(TEST_CLASS, cacheKey, TEST_DURATION, TEST_RETURNED_DATA);

ExecutorService executorService = PriorityThreadPoolExecutor.getPriorityExecutor(1);
requestProcessorUnderTest = new RequestProcessor(getContext(), mockCacheManager, executorService, requestProcessorListener, networkStateChecker, progressReporter,
spiceServiceListenerNotifier);
mockRequestRunner = new RequestRunner(getContext(), mockCacheManager, executorService, mockRequestProgressManager, networkStateChecker);
requestProcessorUnderTest = new RequestProcessor(mockCacheManager, mockRequestProgressManager, mockRequestRunner);

RequestListenerWithProgressStub<String> mockRequestListener = new RequestListenerWithProgressStub<String>();
Set<RequestListener<?>> requestListenerSet = new HashSet<RequestListener<?>>();
Expand Down Expand Up @@ -224,8 +228,8 @@ public void testObservers_with_AddRequest_when_nothing_is_found_in_cache_and_req
// prepare observers

ExecutorService executorService = PriorityThreadPoolExecutor.getPriorityExecutor(1);
requestProcessorUnderTest = new RequestProcessor(getContext(), mockCacheManager, executorService, requestProcessorListener, networkStateChecker, progressReporter,
spiceServiceListenerNotifier);
mockRequestRunner = new RequestRunner(getContext(), mockCacheManager, executorService, mockRequestProgressManager, networkStateChecker);
requestProcessorUnderTest = new RequestProcessor(mockCacheManager, mockRequestProgressManager, mockRequestRunner);

RequestListenerWithProgressStub<String> mockRequestListener = new RequestListenerWithProgressStub<String>();
Set<RequestListener<?>> requestListenerSet = new HashSet<RequestListener<?>>();
Expand Down Expand Up @@ -487,8 +491,8 @@ public void testAddRequest_doesnt_aggregate_requests_with_null_cache_key() throw
assertTrue(mockRequestListener2.isComplete());

}
//TDD for https://github.com/octo-online/robospice/issues/215

// TDD for https://github.com/octo-online/robospice/issues/215
public void testAddRequest_doesnt_aggregate_requests_when_first_one_is_not_processable() throws InterruptedException {
// given
CachedSpiceRequestStub<String> stubRequest1 = createSuccessfulRequest(TEST_CLASS, null, TEST_DURATION, TEST_RETURNED_DATA);
Expand Down Expand Up @@ -796,8 +800,9 @@ public void test_2_spiceservicelisteners_should_be_notified_of_all_events_from_r
// given
PausableThreadPoolExecutor executorService = PriorityThreadPoolExecutor.getPriorityExecutor(1);
networkStateChecker = new MockNetworkStateChecker();
requestProcessorUnderTest = new RequestProcessor(getContext(), mockCacheManager, executorService, requestProcessorListener, networkStateChecker, progressReporter,
spiceServiceListenerNotifier);

mockRequestRunner = new RequestRunner(getContext(), mockCacheManager, executorService, mockRequestProgressManager, networkStateChecker);
requestProcessorUnderTest = new RequestProcessor(mockCacheManager, mockRequestProgressManager, mockRequestRunner);

EasyMock.expect(mockCacheManager.loadDataFromCache(EasyMock.eq(TEST_CLASS), EasyMock.eq(TEST_CACHE_KEY), EasyMock.eq(TEST_DURATION))).andReturn(null);
EasyMock.expect(mockCacheManager.saveDataToCacheAndReturnData(EasyMock.eq(TEST_RETURNED_DATA), EasyMock.eq(TEST_CACHE_KEY))).andReturn(TEST_RETURNED_DATA);
Expand Down Expand Up @@ -869,8 +874,8 @@ public void test_2_spiceservicelisteners_should_be_notified_of_all_events_from_r
// given
PausableThreadPoolExecutor executorService = PriorityThreadPoolExecutor.getPriorityExecutor(1);
networkStateChecker = new MockNetworkStateChecker();
requestProcessorUnderTest = new RequestProcessor(getContext(), mockCacheManager, executorService, requestProcessorListener, networkStateChecker, progressReporter,
spiceServiceListenerNotifier);
mockRequestRunner = new RequestRunner(getContext(), mockCacheManager, executorService, mockRequestProgressManager, networkStateChecker);
requestProcessorUnderTest = new RequestProcessor(mockCacheManager, mockRequestProgressManager, mockRequestRunner);

EasyMock.expect(mockCacheManager.loadDataFromCache(EasyMock.eq(TEST_CLASS), EasyMock.eq(TEST_CACHE_KEY), EasyMock.eq(TEST_DURATION))).andReturn(null);
EasyMock.expectLastCall().anyTimes();
Expand Down Expand Up @@ -956,8 +961,8 @@ public void testRequestPriority_should_execute_asap_hight_priority_requests() th
// when
PausableThreadPoolExecutor executorService = PriorityThreadPoolExecutor.getPriorityExecutor(1);
networkStateChecker = new MockNetworkStateChecker();
requestProcessorUnderTest = new RequestProcessor(getContext(), mockCacheManager, executorService, requestProcessorListener, networkStateChecker, progressReporter,
spiceServiceListenerNotifier);
mockRequestRunner = new RequestRunner(getContext(), mockCacheManager, executorService, mockRequestProgressManager, networkStateChecker);
requestProcessorUnderTest = new RequestProcessor(mockCacheManager, mockRequestProgressManager, mockRequestRunner);

CachedSpiceRequestStub<String> stubRequestHighPriority = createSuccessfulRequest(TEST_CLASS, TEST_CACHE_KEY2, TEST_DURATION, TEST_RETURNED_DATA2);
stubRequestHighPriority.setPriority(SpiceRequest.PRIORITY_HIGH);
Expand Down Expand Up @@ -1002,8 +1007,8 @@ public void testRequestPriority_should_execute_lazyly_low_priority_requests() th
// when
PausableThreadPoolExecutor executorService = PriorityThreadPoolExecutor.getPriorityExecutor(1);
networkStateChecker = new MockNetworkStateChecker();
requestProcessorUnderTest = new RequestProcessor(getContext(), mockCacheManager, executorService, requestProcessorListener, networkStateChecker, progressReporter,
spiceServiceListenerNotifier);
mockRequestRunner = new RequestRunner(getContext(), mockCacheManager, executorService, mockRequestProgressManager, networkStateChecker);
requestProcessorUnderTest = new RequestProcessor(mockCacheManager, mockRequestProgressManager, mockRequestRunner);

CachedSpiceRequestStub<String> stubRequestLowPriority = createSuccessfulRequest(TEST_CLASS, TEST_CACHE_KEY2, TEST_DURATION, TEST_RETURNED_DATA2);
stubRequestLowPriority.setPriority(SpiceRequest.PRIORITY_LOW);
Expand Down Expand Up @@ -1228,7 +1233,6 @@ public void testExecute_when_there_is_no_network() throws Exception {
assertTrue(mockRequestListener.getReceivedException() instanceof NoNetworkException);
}


// ============================================================================================
// EXECUTOR SERVICE DEPENDENCY
// ============================================================================================
Expand All @@ -1237,9 +1241,8 @@ public void testShouldStop_shuts_down_the_executor_service() throws Exception {

// given
ExecutorService mockExecutorService = EasyMock.createMock(ExecutorService.class);

requestProcessorUnderTest = new RequestProcessor(getContext(), mockCacheManager, mockExecutorService, requestProcessorListener, networkStateChecker, progressReporter,
spiceServiceListenerNotifier);
mockRequestRunner = new RequestRunner(getContext(), mockCacheManager, mockExecutorService, mockRequestProgressManager, networkStateChecker);
requestProcessorUnderTest = new RequestProcessor(mockCacheManager, mockRequestProgressManager, mockRequestRunner);

mockExecutorService.shutdown();
EasyMock.replay(mockExecutorService);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ public synchronized void shouldStopAndJoin(final long timeOut) throws Interrupte
throw e;
} finally {
long end = System.currentTimeMillis();
Ln.d("Runner join time (ms) when should stop %d", (end - start));
Ln.d("Runner join time (ms) when should stop %d", end - start);
}
isUnbinding = false;
unbindFromService(contextWeakReference.get());
Expand Down Expand Up @@ -391,7 +391,7 @@ public boolean isAggregatable() {
}

/**
* @See {@link #addListenerIfPending(Class, Object, PendingRequestListener)}
* @See #addListenerIfPending(Class, Object, PendingRequestListener)
*/
@Deprecated
public <T> void addListenerIfPending(final Class<T> clazz, final Object requestCacheKey, final RequestListener<T> requestListener) {
Expand Down Expand Up @@ -1168,7 +1168,7 @@ private boolean tryToStartService() {
}

private void bindToService(final Context context) {
if (context == null || (requestQueue.isEmpty() && isStopped)) {
if (context == null || requestQueue.isEmpty() && isStopped) {
// fix issue 40. Thx Shussu
// fix issue 246.
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
import com.octo.android.robospice.request.CachedSpiceRequest;
import com.octo.android.robospice.request.RequestProcessor;
import com.octo.android.robospice.request.RequestProcessorListener;
import com.octo.android.robospice.request.RequestProgressManager;
import com.octo.android.robospice.request.RequestRunner;
import com.octo.android.robospice.request.listener.RequestListener;
import com.octo.android.robospice.request.listener.SpiceServiceListener;
import com.octo.android.robospice.request.notifier.DefaultRequestListenerNotifier;
Expand Down Expand Up @@ -80,11 +82,6 @@ public abstract class SpiceService extends Service {
/** Responsible for persisting data. */
private CacheManager cacheManager;

private SpiceServiceListenerNotifier spiceServiceListenerNotifier;
private RequestListenerNotifier progressReporter;

private final SelfStopperRequestProcessorListener requestProcessorListener = new SelfStopperRequestProcessorListener();

// ----------------------------------
// CONSTRUCTOR
// ----------------------------------
Expand Down Expand Up @@ -113,20 +110,31 @@ public void onCreate() {
return;
}

progressReporter = createRequestRequestListenerNotifier();
spiceServiceListenerNotifier = createSpiceServiceListenerNotifier();

final RequestListenerNotifier progressReporter = createRequestRequestListenerNotifier();
final SpiceServiceListenerNotifier spiceServiceListenerNotifier = createSpiceServiceListenerNotifier();
final RequestProcessorListener requestProcessorListener = createRequestProcessorListener();
final ExecutorService executorService = getExecutorService();
final NetworkStateChecker networkStateChecker = getNetworkStateChecker();
final RequestProgressManager requestProgressManager = createRequestProgressManager(requestProcessorListener, progressReporter, spiceServiceListenerNotifier);
final RequestRunner requestRunner = createRequestRunner(executorService, networkStateChecker, requestProgressManager);

requestProcessor = createRequestProcessor(executorService, networkStateChecker);
requestProcessor = createRequestProcessor(cacheManager, requestProgressManager, requestRunner);
requestProcessor.setFailOnCacheError(DEFAULT_FAIL_ON_CACHE_ERROR);

notification = createDefaultNotification();

Ln.d("SpiceService instance created.");
}

private RequestRunner createRequestRunner(final ExecutorService executorService, final NetworkStateChecker networkStateChecker, RequestProgressManager requestProgressManager) {
return new RequestRunner(getApplicationContext(), cacheManager, executorService, requestProgressManager, networkStateChecker);
}

private RequestProgressManager createRequestProgressManager(final RequestProcessorListener requestProcessorListener, final RequestListenerNotifier progressReporter,
final SpiceServiceListenerNotifier spiceServiceListenerNotifier) {
return new RequestProgressManager(requestProcessorListener, progressReporter, spiceServiceListenerNotifier);
}

@Override
public int onStartCommand(final Intent intent, final int flags, final int startId) {
super.onStartCommand(intent, flags, startId);
Expand All @@ -139,17 +147,29 @@ public int onStartCommand(final Intent intent, final int flags, final int startI
* return a {@link RequestProcessor}. Override this method if you want to
* inject a custom request processor. This feature has been implemented
* following a request from Christopher Jenkins.
* @param executorService
* a service executor that can be used to multi-thread request
* processing.
* @param networkStateChecker
* an entity that will check network state.
* @param cacheManager
* the cache manager used by this service.
* @param requestProgressManager
* will notify of requests progress.
* @param requestRunner
* executes requests.
* @return a {@link RequestProcessor} that will be used to process requests.
*/
protected RequestProcessor createRequestProcessor(ExecutorService executorService, NetworkStateChecker networkStateChecker) {
return new RequestProcessor(getApplicationContext(), cacheManager, executorService, requestProcessorListener, networkStateChecker, progressReporter, spiceServiceListenerNotifier);
protected RequestProcessor createRequestProcessor(CacheManager cacheManager, RequestProgressManager requestProgressManager, RequestRunner requestRunner) {
return new RequestProcessor(cacheManager, requestProgressManager, requestRunner);
}


/**
* Creates a {@link RequestProcessorListener} for the
* {@link RequestProcessor} used by this service. See a typical
* implementation : @see {@link SelfStopperRequestProcessorListener}.
* @return a new instance {@link RequestProcessorListener} for the
* {@link RequestProcessor} used by this service.
*/
protected RequestProcessorListener createRequestProcessorListener() {
return new SelfStopperRequestProcessorListener();
}

/**
* For testing purposes only.
* @return the request processor of this spice service.
Expand Down Expand Up @@ -210,7 +230,7 @@ protected ExecutorService getExecutorService() {

/**
* Creates the SpiceServiceListenerNotifier.
* @return ({@link SpiceServiceListenerNotifier)}
* @return {@link SpiceServiceListenerNotifier}
*/
protected SpiceServiceListenerNotifier createSpiceServiceListenerNotifier() {
return new SpiceServiceListenerNotifier();
Expand Down Expand Up @@ -248,7 +268,7 @@ public Notification createDefaultNotification() {
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
notification.priority = Notification.PRIORITY_MIN;
}

return notification;
}

Expand Down Expand Up @@ -370,7 +390,7 @@ public boolean onUnbind(final Intent intent) {
return true;
}

private final class SelfStopperRequestProcessorListener implements RequestProcessorListener {
protected final class SelfStopperRequestProcessorListener implements RequestProcessorListener {
@Override
public void requestsInProgress() {
}
Expand Down
Loading

0 comments on commit 3227f2b

Please sign in to comment.