Image for post
Image for post

How to maximize Android’s UI reusability — 5 common mistakes

During the last few months, I had the opportunity to revisit some of our existing UI at Groupon. As part of this process, we started by identifying what is good in our UI and what are our most common mistakes, with the hope of taking Groupon's UI to the next level.

What makes UI good? Good is relative but it was easy to agree on three main principles that can be applied to any software:

  • Readable. Good UI components are easy to read. No need to visit Android Studio’s design tab, the xml is self-explanatory.
  • Testable. Every UI component can be easily tested without depending or external components.
  • Reusable. UI components can be reused and extended without changing their original behaviors.

In this article, we will go through some common mistakes that affect our UI’s reusability and see how reusable UIs can make our code more readable and testable.

1. Business model’s in custom views

We use userApiClient to pull our user’s information from backend:

On success, we receive the model:

And we pass that same model to our custom view UserView, that will show the user’s name and address. This may look like an easy win but it’s not. It goes against our reusability principle and can cause serious problems in the long term. Let’s see why.

Why is this bad?

  • The backend model probably has more information than our view needs. Extra information means, extra complexity. The more information the model contains, the easier it is to use an incorrect field. In the example above, we could have used a simplified model:
  • What happens if backend changes? We tend to assume that the backend services supporting our application will never change. This is definitely not true, our backend will change and we need to be ready for it. We shouldn’t be changing our UI just because something changed in the backend.

How to fix it?

In our example, we will convert UserModel into UserUIModel and pass it as a parameter to UserView:

Our new implementation requires some extra plumbing and adds the complexity of a new transformation but this is a small price to pay to decouple our UI from our backend. Our new design prevents us from sending unnecessary data to our views and allows us to reuse our views wherever we need them.

2. Monolithic views

Why is this bad?

  • These files are really hard to read, too much information and too many layers of components living together.
  • It’s not possible to test each part of the xml individually. We tend to only test our UI as part of integration tests executed in espresso. Integration tests are great but they mix UI and business logic, making hard to know what is the underlying cause of an error. By breaking our monolithic xmls into small custom views and removing all the business logic from our UI, we enable UI only tests. These tests can detect issues in our UI at a more finer granularity level than regular integration tests.
  • We can’t reuse individual parts of our xml, this forces us to copy and paste those individual components in order to reuse them in a different screen. Over time, the duplicated components will start diverging, causing inconsistency in our app.

How to fix it?

Custom views and the <include> and <merge> tags are our best friends. We should always use them to break our UI at the beginning of any new feature. Waiting for a UI component to be reused in order to break it out of a monolithic xml can cause serious issues. At that time, our UI will be heavily coupled with our activity/fragment, making the refactor harder and endangering existing functionalities of our app.

Let’s see an example inspired by a real layout of an open source project. I have removed properties and added comments to make the layout easier to read:

Even after removing properties and adding comments, reading an xml like this is hard. There are several layers of nested layouts, making hard to understand where each component is placed. Without the comments, is hard to tell how the different tags are related and what they represent.

In the xml we can identify at least 6 well-defined UI components. Let’s see how this layout will look like if we create a custom view for these components:

By creating a custom view for each of our views we simplified our code, made our views reusable and prevented the side effects of future refactors. In this new implementation, the comments are no longer necessary because our code is self-descriptive.

Think how easy it will be to implement a new progress animation if all our activities use ProgressOverlay. It will only require to change one class vs all our activities using the monolithic approach.

Groupon’s approach of favoring small UI components over monolithic xmls it is inspired by Brad Frost’s book Atomic Design. I recommend taking a look at this book, especially if you are passionate about UI.

3. Business logic in custom views

Why is this bad?

  • Adding business logic to our views makes it harder to test our views. Well-implemented views only depend on smaller UI components. They can be easily tested in isolation as part of an automation test. Good automation coverage, at the view level, will help us detect earlier undesired side effects of refactors and code changes in our UI.

How to fix it?

At Groupon, we have found that MVI and unidirectional data flows are a great way to fix this problem. The business logic should be part of our Intent, that will produce an immutable state object, that will be rendered by our view.

If you are interested in unidirectional data flows and how to implement reusable UI components. I strongly encourage you to read Pratyush Kshirsagar and Yichen WU article Cross view communication using Grox. They do a great job explaining how unidirectional data flows can help us build our UI.

4. Over-optimization

While we do believe that performance it is important, readable, reusable and testable code is even more important than optimized code. After all, that’s the reason why we use high-level programming languages instead of writing more efficient assembler code.

In Android, nested layouts and double taxation are two big problems that affect the performance of our UI. Because of that, we are constantly bombarded with articles, podcast and talks telling us to use ConstrainLayout and avoid nested layouts. ConstrainLayout is an amazing tool, is more powerful than RelativeLayout and it doesn’t incur in double taxation. The problem, as usual, happens when we take this to the extreme.

Based on all the articles and talks that we have heard, we may decide that we are going to implement the UI of our activity only using one ConstraintLayout.

Why is this bad?

  • We are not treating our UI as a first-class citizen. We will never consider building all our business logic in the activity/fragment class. Exactly the same reasons apply to not building our UI one xml file.

How to fix it?

5. Neglecting our UI in code reviews

Why is this bad?

  • We are not treating our UI as a first-class citizen. Our UI is half of our app, spending time reviewing xmls and views is, at least, as important as reviewing our business logic.

How to fix it?

As a reviewer:

  • It’s perfectly fine to recognize that we are not able to understand an xml. You probably don’t have the right context or the UI is too complex. Ask for help from the author of the code.
  • Don’t feel bad about asking the author to break an xml into smaller views. You will do the same with for large class or a large method.
  • Start the code review with the UI. As I said, xml files are the hardest part to review, don’t wait to be tired to start reading them.
  • Be familiar with the Material Design guidelines. Some easy things I always check are: Do we have a ripple effect as part of our “pressed” state? Do we have/need elevation in our buttons? or Do our animations have the right duration?

As a reviewee:

  • Add screenshots of your UI in your Pull Request. This will help your team review the code faster.
  • Ask your designer to review your implementation. Your designer is your greatest ally. Ask them to review your UI as early in the development cycle as possible.
  • Avoid monolithic xml files. I can’t say this enough, small UI components are better and easier to review.
  • Start with your UI. Start any new feature by creating a Pull Request dedicated to your UI. This way you know that your UI will have 100% of the reviewer’s attention.


Reusing our UI help us build new functionalities faster. There is a big difference, in terms of speed and quality, between composing existing UI components and building a complete UI from scratch. Also, reused components contain bug fixes and consider edge cases we may have never thought about.

Summarizing some of the tips that we have discussed:

  • Using business models for views is a bad idea. Always decouple your views from your backend and your business logic.
  • Avoid monolithic xmls. They make your code hard to read, hard to test and they are the main cause of inconsistencies in an app. Atomic Design can help you break your UI into reusable components.
  • Business logic doesn’t belong in the UI. Logging, AB testing or decision making logic don’t belong in a View. Views should only receive an immutable state and render it. Embracing MVI, immutability and unidirectional data flows will help you.
  • Optimization on the expense of code quality should be an exception, never a rule. We should only create monolithic views to avoid nested layouts’ penalizations when there are no other options. Build your UI the right way and tackle performance issues only when they actually happen.
  • Treat your UI code as a first-class citizen. Start any feature by building its UI first, ask your designer to review it as soon as possible and ask your team to review it independently.

I hope these tips help you with your next Android adventure. With 💚 Carlos Palacin Rubio from the Groupon Android team.

Groupon Product and Engineering

All things technology from Groupon staff

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store