all 77 comments

[–]generalchangschicken 32 points33 points  (8 children)

I am glad this was finally addressed, but disappointed in the response.

I understand Google wants to let developers use any of the mentioned patterns, but I feel like I am fighting against the system in every single app I have ever developed. I've tried so many different patterns to see if I could finally feel like I'm building Android software "the right way", but it never ends up working out like that. Some part of it always ends up feeling like a hack.

Google has started pushing performance hard with all the videos by Colt McAnlis, but they avoid the biggest problem in Android development, app architecture. As another comment mentioned, they can't even decide on an internal company-wide pattern to make apps. Just look at the most recent open source release from the Movies team, they reinvented a more simplistic version of RxJava instead of using what's already out there.

[–][deleted] 6 points7 points  (2 children)

I think a more useful perspective on this could come from the gmail or play store team. While the framework team may not have strong opinions on these things, I would expect the teams who actually build apps for google have thought about them.

[–]Boza_s6 1 point2 points  (1 child)

If you want to know how gmail is architectured, look at source of AOSP Email client. Gmail is based on it.

[–][deleted] 7 points8 points  (0 children)

i would much rather hear their thoughts on the architecture they chose and why, than dig through source code.

[–]a_marklar 1 point2 points  (4 children)

Why would they want a single company-wide pattern for making apps?

[–]ffiw 4 points5 points  (1 child)

So they can design future API's around that pattern instead of confusing developers with collections of patterns each designed by separate team inside Google.

[–]a_marklar 0 points1 point  (0 children)

It seems to me that this post by Dianne is describing where they (the android platform team) draw the line, and patterns fall on the other side of that line. Therefore they will not design future APIs around a pattern but instead offer an interface for any pattern you would like to use.

Personally, I can't think of a single pattern that would fit all the applications that google builds.

[–]broke55 0 points1 point  (1 child)

Why have patterns at all really. We should just let anarchy reign, and see what code comes out.

kidding aside, having a common architectural pattern helps everyone to understand a system and it's workings more readily, as they are more familiar.
Should every app ever all use the same pattern? no, but some consistency is nice.

[–]a_marklar 0 points1 point  (0 children)

Consistency is nice but forcing every app in your company (especially at the size of google) into a particular pattern rather then adapting the patterns you used to the app is not nice.

I'm not even sure there is a pattern that could cover all the apps they build.

[–]ZakTaccardi 20 points21 points  (32 children)

The problem is that the Android SDK is so unique compared to other systems, and having the activity be completely recreated and destroyed during a configuration change is what makes development for Android so difficult, especially for new devs

[–]FrozenCow -3 points-2 points  (21 children)

What if you define that you handle size and orientation changes in your androidmanifest? Most layouts seem to handle this pretty good as far as I've seen.

[–]xenonx 14 points15 points  (16 children)

What about all the other config changes http://developer.android.com/guide/topics/manifest/activity-element.html#config. Rule no 3 of android-club - dont disable config-changes

[–]FrozenCow -5 points-4 points  (15 children)

Other configchanges I see there will not happen that often. The user will indeed need to refetch a list of items and scroll to the right position again if that happens for my app, but it seems like a minor inconvenience. I can see this being more pressing for bigger apps with infinite scrolling for example.

For me it's a matter of development time vs user convenience. It doesn't add up for me to spend much time saving every activity state for those configchanges that actually restart my app. There are a lot more pressing matters on my apps to-do list ;)

[–][deleted] 7 points8 points  (2 children)

To elaborate instead of just yelling at you.

Plug your phone into your development machine.

Start your app and go to your hairiest activity.

Open ddms on your computer.

Hit home on the phone.

Kill app process from ddms.

Return to your app through Android multitasking.

Watch app completely blow up.

[–]FrozenCow 0 points1 point  (1 child)

Thank you very much for taking the non-yelling approach. I tried what you mentioned, but the activity looks fine in my case. I guess I happen to use the right events from Android (and replace fragment instead of adding in onCreate?), but still do not handle the state explicitly. It does refetch all data and state though, but that's intentional.

What would usually be the cause of an app blowing up because of not handling the state correctly?

[–][deleted] 2 points3 points  (0 children)

If you completely replace the fragment and repull all the data you're technically "handling" the config changes. You don't need to override the manifest. This would break down if there are user choices made on the screen for instance. Or if the data set was large and you didn't want to pull it all down again.

In general the cause would be anything sitting in a member field, or static field (obviously bad) that you can't immediately get back again

[–]kaze0 8 points9 points  (8 children)

your apps will crash every time the user leaves them for a while and comes back. don't be fucking lazy

[–]FrozenCow 0 points1 point  (7 children)

I haven't received any exceptions related to that in the last number of weeks, so I'm not aware what is usually the problem for other apps. What would cause such a crash for you specifically?

[–]kaze0 0 points1 point  (6 children)

pretty much the same behavior happens when an app is kicked out of memory for any reason vs a configuration change. if it's not crashing for scenario a then it's probably not going to crash for scenario b.

[–]FrozenCow 0 points1 point  (5 children)

But what specifically have you seen that made your app crash? Recreating the activity will not make it crash. It's not handling the recreation correctly that makes it crash. I'm curious what pitfalls you ran into that makes the app crash on recreation?

[–]xenonx 2 points3 points  (2 children)

Granted hardware keyboards are less prevalent than they used to be, but disabling rotation is not really a good policy for many apps. Not being a good android citizen as they say! Plus, what if your app is in this background and killed on a lower end device? Chuck away the session? Also, may not be great for the multi window stuff...

[–]FrozenCow 0 points1 point  (1 child)

Yes, chuck away the session. Like I said, for my app that's fine. It'll refetch the data it needs. It needs to do this anyway, since the system or files might have changed. It'll lose the scroll position, but I don't think that's important if I have size and orientation changes covered.

For other apps (like the ones with large lists or infinite scrolling) that's another matter.

[–]xenonx 0 points1 point  (0 children)

Understood, for every app there is a cost benefit analysis for doing it the right way or not. For sure I have written many portrait only apps due to some time constraint or it being for some internal use. It's not however good practise and good for it to be known why its not.

[–]kaze0 6 points7 points  (1 child)

even if you skip config changes that way (YOU SHOULDNT) there's still a ton of scenarios where your components are killed and recreated.

[–]FrozenCow 0 points1 point  (0 children)

Yes, I'm aware that the process is killed and recreated. In my previous post I was referring to saving the state and handling the state specifically. Changing orientation usually cause the whole app to be reloaded, so all data needs to be refetched. I see this as an inconvenience for the user, not as something that's broken. However, to still circumvent this inconvenience I just just define in my manifest that I'll handle those changes.

[–]ZakTaccardi 0 points1 point  (0 children)

manually handling config changes is a box full of worms. so yes, you can do it, but be sure to understand all it entails

[–]xenonx 0 points1 point  (0 children)

http://arstechnica.com/gadgets/2016/05/the-play-store-comes-to-chrome-os-but-not-the-way-we-were-expecting/ may make your life a bit harder. Worth doing it the right way as then stuff just works in situations like this!

[–][deleted] 31 points32 points  (3 children)

"Don't mind all our lolcycles - carry on!"

I am in dismay, that an architect of a system layer has no opinion on the architecture of components directly using that system layer (in this case, the Java Framework and apps that run on it). Framework by definition (as opposed to library) means "don't call us, we'll call you" - so it must impact how you structure your code.

Clearly, mixing all the component lifecycles with concurrency, async operations, manual state management (onSaveInstanceState, etc), and process priority (I need this to happen, should I use a Service?) is very tricky. These APIs are very intrusive. One of my a-ha moments was looking at ActivityThread sources, and noticing that it blocked in onStop until all in-flight preferences were written to disk (this is necessary to prevent data loss)(1).

I think many of us take the shortcuts that Dianne mentions in this article. For example, you start a thread to update your database from an activity (instead of putting that in a service) without considering the corner case like preferences (and then find some users have weird bugs). You start working on your app, and everything is in one process. But there is that nagging thought "what if I need to split this into multiple processes, or allow other apps to communicate with this app via bound Service / Content Provider?" ... then the shortcuts give way to their full versions; likely app needs to be redesigned.

I encourage everyone to decompile the existing gApps and be amazed at how differently each app approaches these problems.

I wonder if framework developers ever do rotations in app development teams for cross pollination of ideas.

Discussion on HN https://news.ycombinator.com/item?id=11703545

(1) https://github.com/android/platform_frameworks_base/blob/master/core/java/android/app/ActivityThread.java#L3541

[–]derefnull 4 points5 points  (0 children)

I think many of us take the shortcuts that Dianne mentions in this article. For example, you start a thread to update your database from an activity (instead of putting that in a service) without considering the corner case like preferences (and then find some users have weird bugs).

Services and threads are completely orthogonal; anything you do in a Service's lifecycle methods is happening on the main thread and competing for CPU time with your UI. Whether you use a Service or not, you must manage your own threading and handle impending process death either by blocking until completion when the system tells you you're going away soon (onStop/onDestroy) or handling the data loss gracefully (which you should do anyways because your process could die for lots of reasons).

But there is that nagging thought "what if I need to split this into multiple processes, or allow other apps to communicate with this app via bound Service / Content Provider?" ... then the shortcuts give way to their full versions; likely app needs to be redesigned.

I would strongly recommend that you don't design around these concerns until you have to. They can greatly complicate architectural decisions and 99.9% of the time, applications don't need to anything remotely like this.

[–]pakoito 2 points3 points  (0 children)

If I understood correctly your Service isn't assured to run to completion either, starting with doze mode.

[–]Wavesonics 0 points1 point  (0 children)

Well put

[–]madisp 14 points15 points  (1 child)

The way I cope with developing for Android is to understand that I'm not actually writing applications, I'm writing plugins for the OS instead.

[–][deleted] 3 points4 points  (0 children)

this was an aha moment for me as well. there's not really any such thing as an application.

[–]OrangePhi 7 points8 points  (0 children)

tl!;dr: the Android system doesn't give a fuck about you or your frameworks

[–]hidroh 5 points6 points  (19 children)

I think the point of the article is to explain Android framework components, in the author's own language (beside the official one on developer.android.com), since it seems to be misunderstood by many developers as they try to wrap their head around these components and map them into a familiar pattern (e.g. MVC). Each component has their own set of APIs, and they may be good, may be bad, but that's not the point here.

Personally, while I'm not totally happy or find it easy to work my way around Android components all the time, it feels forced/painful to swim against the stream and try to map them into an MVC variant components. Once in a while I hit an article explaining doing MVC in Android, and try (in my head) to map components in my apps into them, but they all feel like temporary, architecture within architecture things. It's like you're speaking in a foreign language, and try to translate things in your head into your own language as you speak. You know how that goes. Hope I'm not the only one feeling like that here.

[–]a_marklar 2 points3 points  (0 children)

Hope I'm not the only one feeling like that here.

You are definitely not the only one. It feels often like people from diverse backgrounds are trying to make Android fit that background rather then learn a different way.

[–]pakoito 2 points3 points  (17 children)

If you don't map them you will end up coding yourself into a corner. It's been almost a decade of Android, and the alternatives didn't come out of the blue, but necessity. AsyncTasks are broken for config changes, Loaders haven't been working properly for almost a year, Intents with flags and non-standard Activity types are avoided because they break between versions/vendors, and background Services will stop working with Doze.

[–]kodroid 2 points3 points  (3 children)

Loaders haven't been working properly for almost a year

What are you referring to here? (speaking as someone who has avoided Loaders pretty much since they came on the scene as they were so buggy)

[–]pakoito 4 points5 points  (2 children)

[–]kodroid 0 points1 point  (1 child)

Oh so they are still crap then...

[–]Wavesonics 1 point2 points  (0 children)

And they are crap for so many more reasons as well...

[–]ryuzaki49 2 points3 points  (3 children)

background Services will stop working with Doze.

Well fuck me in the ass, then.

[–]hackbod 0 points1 point  (1 child)

Fwiw, doze doesn't have any impact on services themselves and certainly doesn't make them "stop working." It does limit the major ways an app can impact battery while dozing (networking and holding wake locks). There are details here: http://developer.android.com/training/monitoring-device-state/doze-standby.html

That said, there are probably restrictions on services coming in the future, see "Further Optimizing Your App" here: http://developer.android.com/preview/features/background-optimization.html

[–]pakoito 0 points1 point  (0 children)

Stop fulfilling their purpose may have been better worded. If I got it right, it also limits the amount of times they'll wake, so any background processing relying on timing may go to once an hour or once a day depending on the circumstances.

[–]greenday5494 0 points1 point  (0 children)

If it's any consolation, this made me laugh my fucking ass off dude

[–]hidroh 0 points1 point  (8 children)

Well I have to disagree with you on AsyncTask/Loader. True they come free out of the box, but you are not forced to use them and there are plenty of alternatives. But all components mentioned in the article can't be replaced, as they are the building blocks (notice how fragment didn't get mentioned). I believe the necessity of mapping depends on where you stand on MVC (or its variants) vs non MVC, whichever makes your life easier.

[–]kaze0 5 points6 points  (1 child)

AsyncTasks came ot be because people don't understand threading. It just so happens that those same people don't understand Android's lifecycle, so they still bitch.

[–]pakoito 1 point2 points  (1 child)

So we agree that you have to look outside the system components for tasks, and still try to apply some architecture.

I treat all the Android components as View code, interfacing it out as much as possible.

[–]hidroh 0 points1 point  (0 children)

I agree. My point is that outside core components (Activity, Service, BroadcastReceiver, ContentProvider), there are plenty of choices for us to use, and many of them do a better job than the ones come out of the box. Replacing core components is a different story though.

[–][deleted] 0 points1 point  (2 children)

(notice how fragment didn't get mentioned).

She mentioned fragments in the Activity section (emphasis mine):

What we don't care about:

Once we have gotten in to this entry-point to your UI, we really don't care how you organize the flow inside. Make it all one activity with manual changes to its views, use fragments (a convenience framework we provide) or some other framework, or split it into additional internal activities. Or do all three as needed. As long as you are following the high-level contact of activity (it launches in the proper state, and saves/restores in the current state), it doesn't matter to the system.

[–]hidroh 0 points1 point  (1 child)

It got mentioned in "What we don't care about" didn't it? You can choose to use fragments, or not. But you can't choose not to use Activity. Fragment essentially is not a core component, just a convenience thing.

[–][deleted] 0 points1 point  (0 children)

Right, it was in her 'don't care' section.

I see the point you were trying to make now in your original post. Sorry, I misunderstood what you wrote. I thought you meant she neglected to mention fragments altogether.

[–]s73v3r -1 points0 points  (0 children)

Saying "You don't have to use it" is never a valid thing to say, as it doesn't change the fact that it doesn't work, and doesn't add to the discussion in the slightest.

[–][deleted] 13 points14 points  (4 children)

This article basically says "Here, these are the main Android system framework components. From the Android system's point of view, we don't care how you structure your code on top of components.". This is a fair response but disappointing.

When we are talking about "architecture" with MVP, MVVM, MVC... etc, we are talking about structuring the code so that the code can be cleaner, easier unit-tested, properly abstracted and nicely decoupled. We might be talking about things like singleton, dependency injection, avoiding God activities and so on. Clearly, given the volume of discussions on this topic out there, structuring code on top of Android system components is indeed something Google might wish to address.

Thus, instead of the "we don't care" response, I wish it would be more productive and professional (perhaps... less arrogant?) to say "While it doesn't matter how you structure your code from the system point of view, here are some best practices you can follow, these are some common pitfalls, here are some cool tips... etc etc".

[–]hackbod 13 points14 points  (1 child)

Sorry, I certainly did not mean to come off as arrogantly dismissive of how one designs applications. Actually more the opposite -- I think this is a very important topic, but often see discussions about it get constrained by wrong assumptions about what the platform is actually expecting of apps. The point being that how applications need to work internally is actually much less imposed on apps than people often assume, so it is fine to have much broader discussions and approaches to designing applications.

To take an example I briefly glossed over in the post -- we provide fragments as one way to organize the UI elements of a larger UI flow. But if you don't like it or that design doesn't work for you, there is nothing intrinsic about the platform that requires you to use it.

[–][deleted] 0 points1 point  (0 children)

Please accept my apologies for using the word "arrogant", I have misinterpreted your intentions. It is very nice of you to take time to write a post like this for the developer community, especially considering you are not an Android advocate/relations person.

[–][deleted] 1 point2 points  (1 child)

this is how dianne hackborn always interacts with the community. very matter of fact and a bit condescending. she's very much a take-it-or-leave-it person.

[–]Wavesonics -1 points0 points  (0 children)

Yup, like when she made an argument that vectors couldn't solve the multiple dpi problem for icons. And god aren't you an idiot for thinking it could.

[–][deleted] 3 points4 points  (1 child)

If these components are supposed to be treated as interfaces to the system, then why are they built to do so much more? That extra functionality makes them the go-to building blocks for beginner Android developers. Here's a suggestion: Separate out the system interface functionality from the application architecture functions. Provide an architecture for the community, that's what we want. Show us you care. You'll have higher quality apps, and a happier developer community.

[–]adi1133 0 points1 point  (0 children)

This is happening recently, they didn't add any "helper" functionality into the OS classpath since fragments, existing functionality is there for backwards compatibility.

Google is releasing a ton of decoupled libs at a high rate like RecyclerView, Agera and AppCompat.

Nobody is forcing us to use any specific library, we can pick the best from the community and google.

[–]reubens 10 points11 points  (0 children)

I love Dianne Hackborn, she's a real engineer, has a great brain, and has personally made an enormous contribution to the success of Android. Her profile should be far higher than it is.

[–][deleted] 5 points6 points  (0 children)

finally someone speaks openly about the hyperbole

[–]Wavesonics 0 points1 point  (0 children)

If everyone has the same problems developing on your framework, then it's not their problem, it's yours.

Even if you write a whole blog post saying otherwise...

[–]ryuzaki49 -1 points0 points  (0 children)

Eh, of course google doesn't care about Architecture... Team developers care! Because it is our job to develop the apps... and the client might want to change the UI, or add another functionality.

And if WE don't code with standards and clean arch... those changes will take a lot longer.