9 ms·
A while back, Dianne Hackborn famously said: "We often see questions from developers that are asking from the Android platform engineers about the kinds of des
by clumsysmurf 10y ago
A while back, Dianne Hackborn famously said:
"We often see questions from developers that are asking from the Android platform engineers about the kinds of design patterns and architectures they use in their apps. But the answer, maybe surprisingly, is we often don't have a strong opinion or really an opinion at all." (1)
While that may have been a lofty ideal, in practice Android has many strict requirements on how you partition your code between Activity, Fragment, ContentProvider, and Service classes. Never mind testability and all the new semi-opaque / intelligent battery optimizations Android applies to your app.
After all these years, I still find the most difficult and un-natural thing is mixing concurrency / background tasks that must outlive the UI with complex UI component lifecycles. This is a frequent and necessary thing to do, and also quite awkward. The result is unnecessary complexity that often and easily permeates the code. Dianne says they have no opinions on architecture, but where I disagree is concurrency is an architectural concern and there are definitely many corner cases & snafus mixing that with Android APIs.
(1) https://plus.google.com/+DianneHackborn/posts/FXCCYxepsDU https://plus.google.com/+DianneHackborn/posts/FXCCYxepsDU
- gjolund 10y agoThis is an excellent comment, and it mirrors my experience with android also. Most of the responses Ive gotten from coworkers is "what would you change". I have a hard time answering that.
- cel1ne 10y agoIf one were allowed to break backward compatibility I could come up with a list of changes easily.
- deleted 10y ago[deleted]
- RivieraKid 10y ago> After all these years, I still find the most difficult and un-natural thing is mixing concurrency / background tasks that must outlive the UI with complex UI component lifecycles. Completely agree. I've been developing for Android since 1.0 and the complex interaction between background tasks and activity lifecycle is the worst part of Android that a significant majority of devs get wrong, introducing subtle bugs. (And the worst thing is that the documentation pretends like this issue doesn't exist last time I checked. Newbie developers have no chance getting this right, even experienced dev often ignore it.) Overall, I wouldn't say Android is poorly designed, it's just mediocre, I would expect more from Google. In general, I'd say the design lacks simplicity and elegance. Some examples: - Fragments. Activities were already overly complicated and for some mysterious reason they took it to the next level with fragments. (They should get rid of or redesigned activities too.) - Older version of Google Cloud Messaging library - hundreds of lines of source code to implement a basic hello world example (wth)? - Documentation is unclear in some cases, promoting some cargo cult patterns such view holders (zero effect on performence these days). Also, services, if you don't need IPC, the only "feature" of a service is that it lowers the probability that the app gets killed. I usually just create a simple service and start / stop it as a way to telling the system "don't kill the app".
- chinhodado 10y agoI used to think Activity lifecycle management is complex. Then I learned about Fragments and I started to loathe every moment I have to work with them. What a bloated mess: http://staticfree.info/~steve/complete_android_fragment_lifecycle.png http://staticfree.info/~steve/complete_android_fragment_life...
- sgc 10y agoI started making a semi-complex android app as my first project. Saw the recommendation to use fragments, and I have never looked back because I am way, way too far down the rabbit whole. It's main advantage to me is perhaps nothing. I have no idea and no real way of knowing. But is has tripled my code base, so that is a good thing!
- 10y ago
- cel1ne 10y agoI agree, that's why I don't use fragments at all and do all my multithreading in the way of communicating sequential processes: via BlockingQueue communication to hand-written background threads / services. The trick with Android-development really is to acknowledge that large parts of the SDK are just crap and that you are better served writing custom code than trying to use it.
- m_fayer 10y agoI agree completely. After a while I abandoned fragments completely and started using custom views everywhere. Life got much easier and I kept waiting for the other shoe to drop - decreased maintainability, performance, robustness... something would bite me in the ass for "going my own way." But the shoe never dropped, life did get easier. Lesson learned.
- blumomo 10y agoThanks for sharing your experience with using custom views only. These views would then simply act as the view controller I guess, having not much presentation logic. I was always having this in my head but then I never tried it out so far. Are you going even that far to use one Activity per app only?
- cel1ne 10y agoI do that, but i didn't built an app so far where an activity could be directly started from "outside".
- m_fayer 10y agoNo I have several activities, but they're very coarse-grained. Similar to how a large SPA may consist of a grand total of 3 or 4 pages, and routing works within pages, not just between them. Also, I'm currently using this technique with Xamarin, which opens up some techniques that would be hard to pull off with native. So in this case I use an Angular-style MVVM pattern, so the custom views are all bound to corresponding viewmodels. So the custom views all share one small piece of code that takes care of some binding-related plumbing, and otherwise they're nothing but AXML with binding statements in it. This adds up to a rather pleasing approximation of a web-frontend-style component-based architecture. Xamarin should really be more popular!
- sandGorgon 10y ago> After all these years, I still find the most difficult and un-natural thing is mixing concurrency / background tasks that must outlive the UI with complex UI component lifecycles. This is a frequent and necessary thing to do, and also quite awkward this is being fixed. The problem is that this is political as well as technical. The solution went from GCMNetworkManager to JobScheduler to the now recommended Firebase Jobdispatcher (https://developer.android.com/topic/performance/scheduling.html#fjd https://developer.android.com/topic/performance/scheduling.h...). P.S. Firebase was a newly acquired startup at Google. Firebase Jobdispatcher should be able to take care of your concurrency issues in a power efficient way.
- ntlve 10y agoI've found that the best way to deal with this complexity is to ensure that any concurrent work is done in a fire-and-forget kind of style. Concurrent work is submitted to a IntentService (possible backed by a thread pool instead of a single worker thread to speed things up) and if it needs to talk back to the UI it does so via a local sql-db or similar construct. That way the UI can die and get restarted indepedently of the worker service and the worker service can update UI state without having to care about the UI existing or not.
- rmsaksida 10y agoThis looks like absolutely the best approach, but there's one thing I don't like about it: communication between IntentServices and the UI thread feels so... wasteful. The sanest way to do it, I think, is keep communication to a minimum, relying solely on the local DB as a source of information. But then every operation you do to fetch remote data immediately results in at least a couple of DB operations (store it, read it) and a ton of serialization. As far as I know, there's no simple way to pass an object from the service to the UI.
- kllrnohj 10y ago> As far as I know, there's no simple way to pass an object from the service to the UI. They are in the same process, you can communicate between them through all the normal Java mechanisms. For example, your UI can just register & unregister a callback on the service directly in its start/stop methods (or in onVisibilityChanged if you'd rather do this in a View instead)
- rmsaksida 10y agoOh, that's better then. In documentation they always point you towards using complicated mechanisms for communication, but I suppose that only applies to services running in different processes. Thank you for the clarification.
- mncolinlee 10y ago"After all these years, I still find the most difficult and un-natural thing is mixing concurrency / background tasks that must outlive the UI with complex UI component lifecycles." This and the weaknesses of AsyncTask are the reason why RxJava has been adopted so quickly on the Android side. Event buses are dead or dying. With that said, Rx is still a moving target and it seems to attract a proliferation of redundant, but slightly different, operators that scare away newbies. Observables, schedulers, and map/flatMap/filter are immensely useful to any old school Android developer.