Thanks for the comments. I now get more sense of it, and have a few "thoughts"
inline.
Kind regards,
---
Yavuz Selim Yilmaz
SUNY at Buffalo
Computer Science and Engineering
PhD Candidate
On Jul 26, 2013, at 10:42 AM, Summers Pittman <supittma(a)redhat.com> wrote:
Be warned I'm only on my first cup of coffee :)
On 07/25/2013 12:20 PM, Yavuz Selim YILMAZ wrote:
> Hi all,
>
> When I was using AeroGear iOS, I needed to read from pipe and execute the success and
failure blocks in background (for background data syncronization, a basic one which
provides eventual data consistency). What I did first was this:
>
> dispatch a thread
> read from pipe
> --- READ ---
> success
> --- SUCCESS BLOCK ---
> failure
> --- FAILURE BLOCK ---
>
> However, when I checked, I realized that the success and failure blocks were being
executed on the main thread, not on the thread that I initiated the read. Then I needed to
modify the code and do like this (I know all "--- READ ---"s are already in
background):
>
> read from pipe
> --- READ ---
> success
> dispatch a thread
> --- SUCCESS BLOCK ---
> failure
> dispatch a thread
> --- FAILURE BLOCK ---
>
> At that time, I was going to ask the reason behind dispatching back to the main queue
for success and failure blocks, but then I thought the idea is coming from Android's
AsyncTask. So my wrong assumption made sense as I thought having similar way of handling
the end-developer (hope you get what I mean by end-developer) operations (in this case
read from pipe) would help to use same/similar software architectures for different
platforms (iOS and Android in this case).
>
> Then I started to taste AeroGear Android from the last week. Keeping my hard times
with multithreading on iOS in mind, I was expecting to see the read from pipe code
something like this:
>
> create AsyncTask
> doInBackground
> --- READ ---
> onPostExecute
> success
> --- SUCCESS BLOCK ---
> failure
> --- FAILURE BLOCK ---
>
> However, what I've seen on RestAdapter was quite different:
>
> create new thread
> --- READ ---
> success
> --- SUCCESS BLOCK ---
> failure
> --- FAILURE BLOCK ---
>
> And here, success and failure blocks are being executed on the background thread
instead of on the UI thread. I checked why not using AsyncTask for this operation (as I
was using it for my network operations if I need to touch the UI thread at onProgress and
at onPostExecute), and I realized that there is a reason behind using ThreadPoolExecutor
(no deep research though, I only know it is recommended considering the operations might
take longer).
The reason we use the thread pool executor is because the onPostExcute method runs on the
UI thread. If your Pipe is running form a service that means that things happening on
onSuccess would block the UI thread. This wouldn't be obvious to the user.
Makes perfect sense. :)
> So, in Android case, making sure the availability of the UI thread when executing
success and failure blocks is left to the end-developer as far as I could see (please
correct me if I am wrong),
So the threading bits aren't explicitly defined in the Pipes 101 doc. What the docs
say to do will get you around this issue though. If you use the Pipeline get methods
which take in some form of context (Activity, Fragment, fragment activity, etc) then you
will have onSuccess run on the UI thread. Otherwise you want.
The way pipeline handles the lifecycle of the request and threads makes perfect sense. My
concern now is, as an outside developer, I start with getting started guides, and going
through step by step, pipe (RestAdapter - "first example") provides me a way to
read from endpoint, but it doesn't fit to the "most common" scenario, which
I think is (as Christios mentioned) "networking on the background, update UI on the
success block" (though I can still update the UI, the activity might or might not be
available at that moment). So I feel like, even if I don't know what pipeline is (at
that moment), the "first example" should fit to the basic scenario so it should
use pipeline (in current aerogear-android implementation). But mine is just an idea. :)
Sounds like a trip to the JIRA mobile for better docs.
In general you want to use these methods because it tells lets AG do some smart things
behind the scenes with respect to managing the network, data caching, etc.
With pipeline, yes, aerogear does all the magic. :)
> while in iOS case the execution of the success or failure blocks indicates that the
main thread is up and running at that time. The difference is maybe because of the way iOS
and Android handles the execution of the background threads. But, when first tasting the
libs for both platforms, I did not feel comfortable with (it was not so obvious) on which
thread the success and failure blocks are executed.
>
> So, my first question is, can somebody point me where these threading designs were
discussed?
Probably not. The best thread I can think of would be back from February but it really
doesn't define anything.
> I am curious about the idea behind these designs (platform pushes that way? easy to
implement? common way of doing network operations? or any other specific reason?), and
hoping to learn new things from there (actually I am sure I will).
The goals behind the design were to leverage as much of than Android API to handle the
activity lifecycle as possible. It did mean that there are somethings which just have to
be "known" and the docs should highlight them. IE if you are calling things
from an Activity or Fragment then you should pass the context to the pipeline.get method.
If the docs aren't clear (or if we need to explain the full implications) then that is
a JIRA.
This I think goes to my "the 'first example' should fit to the most common
scenario" statement, if the first example does so, things are getting clear while
going further. But I won't expect everybody to go over "all" the guides and
docs before using AeroGear (e.g. maybe my bad, but I'm using many libs which I
didn't read "all" of their docs and guides yet), and even if the developers
don't know how AeroGear does the things, they should be able to use its magic from the
start. :) (just an opinion though)
For iOS, I checked why AFNetworking defaults to the main thread instead of whichever
thread initiates the call, and I've seen an odd explanation. Here is the brief
scenario:
The first idea comes from this guy and he provides (to me the solution which makes perfect
sense) this PR:
https://github.com/AFNetworking/AFNetworking/pull/107
This simply works as follows: Whichever thread initiates the request is default execution
thread for success/failure blocks, and developer has option to override (to some other
thread or to main thread). The AFNetworking maintainers find this solution confusing.
After 5 months, they provide this PR:
https://github.com/AFNetworking/AFNetworking/pull/202
This uses the main thread as default, and developer has option to override it (I think
AeroGear developer doesn't even have such an option for now). Here is the explanation
why not the first but the second solution is merged (from one of the second option
supporting developer): "This is discussable, but probably lead to may less bugs due
to people not understanding what they are doing :)" However, this solution and
explanation doesn't make sense to me at all. I think if I'm initiating the request
from the main thread, I might or might not know what I am doing, but if I am dispatching
another thread and requesting from there, I at least know what multithreading is. :) And I
did expect my success/failure to run on the initiator thread when I was trying it out
(maybe it's only me, but I felt it's the natural way - and AeroGear Android
pipeline works this way as far as I could see).
At the least, as Christos said, nothing prevents me to work on the threading, and to deal
with life cycles on my own, but I'm just expecting all the magic (at least for the
common scenario) is done by AeroGear (it's in the end much more powerful than what I
can come up with in a limited time :)). And to me, what AFNetworking provides does not
seem to be a full magic. :) Maybe it's only me who thinks the common scenario is
different.
If people have better ideas then that is a ML thread and then maybe a JIRA :)
>
> Second and the last thing, I think somewhere in the guides and docs, the threading
(best practices when using AeroGear) should be emphasized/mentioned/explained. Because,
although things are smooth and easy when the operations take little amount of time, things
are becoming more complicated when the operations take longer as the device users' app
usage pattern is unknown. (e.g. for Android, I needed to check thread name/id to actually
realize the success/failure blocks were being executed on the background thread (e.g.
Pipes 101 mentions to be aware of Android Activity Lifecycle, but not so clear what
happens during the execution - is it going to stop? is it going to execute on UI thread or
background? will I need to check if UI thread is there or not? etc.).
> And for iOS, I needed to have a really blocking success/failure code to realize it
was running on the main thread, since then I was looking for some other parts to see why
scrolling was not smooth).
>
> Kind regards,
>
> ---
> Yavuz Selim Yilmaz
> SUNY at Buffalo
> Computer Science and Engineering
> PhD Candidate
>
>
>
> _______________________________________________
> aerogear-dev mailing list
> aerogear-dev(a)lists.jboss.org
>
https://lists.jboss.org/mailman/listinfo/aerogear-dev
_______________________________________________
aerogear-dev mailing list
aerogear-dev(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/aerogear-dev