Hi all,
-----------------------------------------------------------------------
---- Skip if you don't want to verify my iOS
tracking ----
-----------------------------------------------------------------------
------------------------------ Start
---------------------------------
-----------------------------------------------------------------------
First, here is what I could track on the iOS side
(please correct me if there's any mistake):
- AGRESTPipe cancel method simply calls the
cancelAllOperations on its restClient's operationQueue
[1].
- AGRESTPipe's restClient is a AGHttpClient [2].
- AGHttpClient is a AFHttpClient [3].
- AFHttpClient's operationQueue is a
NSOperationQueue [4].
- Calling cancelAllOperations on NSOperationQueue
sends cancel message to all Operations in the queue
[5]. If the operation is still in the queue (waiting
to be executed), they are not being executed. If the
operation is alread started to it's execution, it's up
to the "Operation" how to respond to cancel message.
- Sending cancel message to operations sets their
isCancelled flag. Any custom NSOperation extension is
recommended to handle this cancel operation [6].
- AGHttpClient creates the operation by calling
HTTPRequestOperationWithRequest [7], which is
AFHttpClient method. It creates either custom
(AFImage, AFJSON, AFPropertyList, AFXML) operation [8]
or AFHttpRequestOperation [9]. All custom operations
are AFHttpRequestOperation, which is a
AFURLConnectionOperation [10].
- AFURLConnectionOperation implements cancel method
[11] and simply cancels the operation's
NSURLConnection, the connection is cancelled and no
delegate is called [12].
- Then AFURLConnectionOperation calls its delegate
method manually to finish the operation [13].
- The delegate handles the case [14] and finishes
the operation [15].
-----------------------------------------------------------------------
------------------------------- End
---------------------------------
-----------------------------------------------------------------------
---- Skip if you don't want to verify my iOS
tracking ----
-----------------------------------------------------------------------
Simply, what I understand is, operation itself is
responsible to handle the cancel message sent by any
pipe implementation. And on the Android side, the
operations are runnables [16, 17, 18, 19] as far as I
could interpret. So, these runnables should be able to
handle cancel messages which means they should catch
or throw the thrown InterruptedException.
So, the problem is, find a way to send cancel
message to the tasks, and handle the cancel message on
the tasks.
HOW TO SEND CANCEL MESSAGE TO THE TASKS?
1ST PROPOSAL:
RestAdapter is using ThreadPoolExecutor [20]. So,
one way to send cancel message to all running and
queued runnables is to call shutDownNow on the
ThreadPoolExecutor [21]. It has some limitations.
First, shut down destroys the ThreadPoolExecutor, so
it needs to be recreated. Second, the current
ThredPoolExecutor is static, means it will cancel all
pipes if it is shut down, so it needs to be an
instance variable instead of static.
2ND PROPOSAL:
Instead of calling THREAD_POOL_EXECUTOR.execute(),
if we call THREAD_POOL_EXECUTOR.submit() [22], then it
returns a Future representing the task. Future has
cancel() [23], which prevents running the task if it
is not started, and interrupts the task if it is
currently running. Therefore, if we have a collection
of <Future> in RestAdapter (i.e. pipe), then we
can cancel the operations by iterating over the
collection and calling cancel() on each Future. In
this case, at some point, we need to clean
<Future> collection to get rid of the already
cancelled tasks.
HOW TO HANDLE THE CANCEL MESSAGE ON THE TASKS?
I could only come up with a single solution, which
is, adding another catch block to each of the
runnables [16, 17, 18, 19]. Here is what it will look
like:
try {
this.result = ...
} catch (InterruptedException e) {
return; // don't call the callbacks, may need
to check the cause of the interrupt???
} catch (Exception e) {
Log.e(TAG, e.getMessage(), e);
this.exception = e;
}
So, I would like to hear what you think about my
solution, and if you have any corrections, better
solutions, comments, anything... All are most welcome.
Kind regards,
--- REFERENCES ---
---
Yavuz Selim Yilmaz
SUNY at Buffalo
Computer Science
and Engineering
PhD Candidate
_______________________________________________
aerogear-dev mailing list
aerogear-dev@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/aerogear-dev