Android Best Practices and Tips by Toptal Developers

Share

This resource contains a collection of Android best practices and Android tips provided by our Toptal network members.

This resource contains a collection of Android development best practices and Android tips provided by our Toptal network members. As such, this page will be updated on a regular basis to include additional information and cover emerging Android techniques. This is a community driven project, so you are encouraged to contribute as well, and we are counting on your feedback.

Check out the Toptal resource pages for additional information on Android common mistakes, Android job description and Android interview questions.

Use Retrolambda and RxJava to Write Less Code

Retrolambda lets you use lambda functions on the Android if you are using older Java versions (prior to Java 8). Let’s examine the difference:

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        handleClick(v));
    }
});

The same code using Retrolambda:

button.setOnClickListener(view -> handleClick(v));

RxJava is lightweight Java VM implementation of the ReactiveX(Reactive Extensions). It is a single JAR library and supports Java 6 or higher and JVM-based languages. RxJava uses a different approach than classic programming for composing asynchronous and event-based programs by using observable sequences. Let’s examine how we could implement the following behavior:

  1. Every 10 seconds, make a request to the backend and fetch rate information.
  2. In the case of an error, retry three times with a delay of three seconds between each try.

The code using RxJava:

mService = ServiceFactory.createRetrofitService(RatesService.class,
    RatesService.SERVICE_ENDPOINT);

mRatesObservable = Observable.interval(0, 10, TimeUnit.SECONDS)
    .flatMap(n ->
        mService.getRates()
            .retryWhen(new RetryWithDelay(3, 3000))
            .subscribeOn(Schedulers.io()));

mRatesObservable = mRatesUpdater.getRates().doOnNext(rates -> updateRates(rates));

// Stop requests
mRatesObservable.unsibscribe();

In less than ten lines of code, we implemented a custom behavior with the network response. Try to imagine how many lines of code you would need with classic Java code, using callbacks, services, and loaders.

Jack and Jill and Java 8

With Retrolambda, though, keep in mind that it could be deprecated soon because of Jack and Jill, an experimental tool for Android that is available in the N developer preview that provides Java 8 features out-of-the-box. Keep an eye on the updates from Google closely about the Jack and Jill, and switch to native implementation as soon as it is ready.

Contributors

Dmitry Ryazantsev

Freelance Android Developer
Montenegro

Dmitry is an Android developer with more than six years of experience who communicates well and always tries to find the best tech that suits the project. He's experienced with Git, Lua (Corona SDK), RxJava, Dagger, etc. He's worked with a large team to develop the Yandex browser that has more than 10 million installations. He's also developed his own projects: a game with 250,000 installations and published several other apps.

Show More

Get the latest developer updates from Toptal.

Subscription implies consent to our privacy policy

Using REST Architecture with Android

Why and When to Use REST

At the Google I/O 2010 conference, Virgil Dobjanschi made a great presentation about implementing REST (representational state transfer) clients in Android, titled Developing Android REST Client Applications. His premise is that Android applications should have a separation between state synchronization and state presentation, and that REST makes doing this much easier.

Virgil’s proposed REST architecture makes it so that a user can begin downloading content, and regardless of what they do with the client (like quitting before the download completes) that content will be ready upon their return. Furthermore, since REST architecture assumes that every unique URL represents a unique state, the user can be sure that the downloaded data is up-to-date. In cases where content is being modified often or needs to be in real time, the server should explicitly prevent cached results (the approach used on auction sites and web stores with a shopping cart).

REST is ideal when the information being presented by the client application has semi-permanence, such as the content of a social network timeline or the history of a chat room. This is because there’s a good chance that it will still be up to date in several hours or days.

Nowadays, most applications that present online content for users are REST clients, and there are tons of services and startups developing mobile versions of their products using REST. However, not all online applications need to be REST clients. As with all technologies, it’s important to understand when you need to develop a REST client application.

In order to be RESTful, an application must fulfill two requirements which improve scale and performance, but if the app violates either of those constraints it cannot be considered RESTful.

What It Means to Be RESTful

Have Unique URIs

A RESTful application must have different states presented to the consumer, and each of these states must have a unique uniform resource identifier (URI) to describe it.

For example, consider a catalogue with a unique page for each product. If the URL formula is something like server.com/catalogue/?item=XX, a toaster might have the page url of server.com/catalogue/?item=toaster9000. Likewise, if an account screen is needed, something like server.com/account exists, and a profile page might be server.com/profile, and so on.

Use Stateless Server-Side Data Storage

All data in a RESTful application should be stored on the server-side. When the client-side needs to define its state with that data, it queries the server with just enough information to get what it needs, and the server merely serves a response. It doesn’t know anything about the user’s context.

This can be trickier than it sounds. Consider a chat application where each chat message has a dialogue ID linking it to the conversation it belongs to. Standard chatroom behavior is to track the current state of the dialogue and only deliver the most recent chat message, once, to the user. If the current state of the dialogue is stored on the client side, that’s RESTful, but if it’s stored on the server (for example, the server knows what chat room the current user is in, and the only necessary info to send a new message is the user’s text, but not the whole information chatid+message), the application is in violation of the REST rules.

REST Patterns

Libraries That Make REST Simple

While one could implement every pattern described by Virgil in his Google I/O presentation, or create custom logic following REST rules by him or herself, reinventing the wheel isn’t worth it. There are many libraries that address the main uses of REST, and I suggest two libraries in particular: RoboSpice and Retrofit.

RoboSpice provides a flexible cache out-of-the-box, so you only need to configure how long a response should be cached, and during that period of time you will receive the saved response. You don’t need to think about the network magic beyond what is needed for the business logic of the application. The main disadvantage of this library, from my point of view, is that you need to describe all of your application’s requests in different classes. If a different return type is needed, likewise a new class is needed. If you need different parameters in a pre-existing request, a new class is needed and so forth. This can get messy.

The other library I recommend, Retrofit, encapsulates calls to your web service by allowing you to describe your backend URLs as interface methods. It turns your HTTP API into a Java interface, and so you can return data from your model to the web service endpoint.

For example, in Java normally you might have:

ReturnType getSomeData(ParamType parameter);

While with Retrofit, the method is annotated with a back-end URL:

@GET("/rest_path/")

Try these libraries and others, find the way you like to solve your problems, and maybe you’ll be inspired to implement your own library!

Contributors

Dmitry Ryazantsev

Freelance Android Developer
Montenegro

Dmitry is an Android developer with more than six years of experience who communicates well and always tries to find the best tech that suits the project. He's experienced with Git, Lua (Corona SDK), RxJava, Dagger, etc. He's worked with a large team to develop the Yandex browser that has more than 10 million installations. He's also developed his own projects: a game with 250,000 installations and published several other apps.

Show More

Some Words About Android Security

While I believe that everything can be hacked, you as the developer are responsible for defining the cost of breaking your app’s security. It’s easy for malicious parties to compromise requests and responses with only with released app from the Google Play store, without any reverse engineering, and so defending communication between the server and client is vital.

It feels like some developers think all their users will be honest, and so they do not implement any security measures to protect communications between the server and the client. Sure, there are methods of obfuscation and signature checkers, but if the online requests and responses are not secured in the first place, they can’t prevent hacking or cheating via MITM attacks.

Imagine that you are creating an online chat application, and you know something about security. Before each message is sent, a CAPTCHA must be cleared, obfuscation is used, and computation of checksums are performed. The client side is secured, so only messages from this particular APK could be sent via your service. But what happens on the other side? What if the other side receives a plain message? With a plain message, there are no guarantees that someone hasn’t changed the messages in transit. You might as well have no security at all.

Even without expensive certificates and HTTPS, there are several helpful methods to improve the security of online communications:

  • Make a signature for each request and response by combining the data, a timestamp, and salt (the secret key that only server and the app know), then hash it with something like an MD5 hash function. Of course this isn’t completely foolproof, the key can be found in your APK, but now it’s much more complex to spoof message content.
  • In addition to MD5, you can complicate the process of extracting the secret key from your app by storing pieces of it in separate places and combining it at runtime. Pieces of the key can be stored in constants, hard coded in the source, and stored in resources. Combined with a custom algorithm or ordering to put the pieces back together, even if the hacker gains the secret key from a previous point, they still don’t understand how the signature is generated.
  • Do not rely on client side computations. If you need to check order status or confirm permissions, do it on the server side and return a signed response. If you’re developing an online store, check if the user bought your goods by their transactions on the server, don’t trust the client to take care of order status. If your application is a game, confirm what actions are available for the user on the server side (constructing a new building, what funds are available for purchasing new items, etc).

If security is vital to your application, which is the case when you’re dealing with real world money, it’s best to implement additional security with tunnels, https, and certificates. However, the above recommendations are sufficient for an application that isn’t handling sensitive information.

Contributors

Dmitry Ryazantsev

Freelance Android Developer
Montenegro

Dmitry is an Android developer with more than six years of experience who communicates well and always tries to find the best tech that suits the project. He's experienced with Git, Lua (Corona SDK), RxJava, Dagger, etc. He's worked with a large team to develop the Yandex browser that has more than 10 million installations. He's also developed his own projects: a game with 250,000 installations and published several other apps.

Show More

How to Properly Run Background Tasks While Updating the UI

Applications often need to perform a lot of time-consuming tasks; these are best performed in the background. The usual way of doing this in Java is by using the Thread class; spawn a new thread, do all the necessary tasks, and you are done. But, what happens if we need to notify the UI? When a background task needs to submit regular updates to the UI Thread, we face a problem because background tasks cannot interact with anything running on the UI thread.

Android has a convenient construct called AsyncTask that allows you to perform background tasks and post updates to the UI thread. Extend your class with AsyncTask, override the proper methods, call the execute function, and you’re done. A first timer, however, will find it a bit tough to grasp at first; there are a couple of rules to follow and constraints to be aware of.

Let’s examine how multithreading works in the Android world. An application starts with one thread, also called the main thread or application thread or UI thread. This thread contains the loop that handles various “events” for the app, some of which are visual updates, such as button-click visual changes, TextView display changes, drawing, and the like. Spawning a new thread to perform a background task causes your app to own two threads, one for the UI and one for your task. How do you access the UI thread from the background task? Well, you don’t. What you do is request that Android add an event to the main loop; it announces to your app that something needs to happen on the main thread and it is providing the “something.” The event will be processed eventually (it’s not a priority), and the UI will be updated.

Now, how do we make this request?

You need two things: a Handler (android.os.Handler) and a Runnable (java.lang.Runnable). The Handler is the announcer, and the Runnable is the event. Create a new handler (new Handler()) outside your background thread, somewhere in the activity and make it available to the thread, which is important as you can only create a thread inside the main thread. Next, create an instance of Runnable and override run() method with what you want to happen in the main thread (such as updating a TextView via setText method). All that’s left to do is call handler.post() and pass the Runnable as an argument. Very often, these three steps can be compressed down to an (albeit nasty looking) one liner:

new Handler().post(new Runnable() {
	@Override
	public void run() {
		// UI update code here
	}
});

Running a background task and updating the UI this way is simpler and faster than implementing an AsyncTask class. However, if you do find yourself having to make more than a couple of calls to handler.post, and your thread frequently updates the UI thread for long periods of time, using AsyncTask may be the way to go.

Contributors

Faye-Lino Agli

Freelance Android Developer
Canada

Faye-Lino is a results-driven IT professional with a proven track record of implementing technology to drive business performance, productivity, and creativity. He's fluent in English and French. He has a lot of experience taking a client's idea making a fully scoped project and seeing it through. He communicates well and can work in a team or solo.

Show More

Use Android Studio 2.0+ to Develop Your Android Applications

IDEs improve development speed, and there are many options you use, like Eclipse or IntelliJ IDEA. However, the best option is to use the Android Studio 2.0+. Android Studio is made just for Android projects, it is made by Google, on top of the IntelliJ IDEA. Additionally, here are few tips how to utilize the Android Studio better:

  • Use hotkeys. There are tons available and they will help simplify your life and increase your productivity. For more information, check the list of keyboard shortcuts you cannot miss, productivity guide and the keypromoter plugin.
  • Use Instant run. Instant Run, introduced in Android Studio 2, significantly reduces the time between updates to your app, as it pushes subsequent updates to your app without building a new APK, so changes are visible much more quickly.
  • Use the multi-window feature. You could save time switching between panels if you use several monitors and place different parts of the IDE UI on a different monitors.

Contributors

Dmitry Ryazantsev

Freelance Android Developer
Montenegro

Dmitry is an Android developer with more than six years of experience who communicates well and always tries to find the best tech that suits the project. He's experienced with Git, Lua (Corona SDK), RxJava, Dagger, etc. He's worked with a large team to develop the Yandex browser that has more than 10 million installations. He's also developed his own projects: a game with 250,000 installations and published several other apps.

Show More

How to Pass Data between Activities and Services

In almost every Android app, Activities (a set of UI elements allowing users to interact with an app) and Services (an OS managed background thread) pass data between themselves. A developer’s task is to decide which method to use to accomplish this task.

When learning the ways of the Android SDK, Google suggests that the correct way of sending data from an Activity or Service to another is by using Intent Extras, which allows you to easily pass and retrieve primitive data types. The putExtra and getExtramethods, and their variants, are single line calls, and are handy for passing simple data along. However, a problem arises when you need to send complex objects.

To pass an object via Intent, it needs to be Parcelable, Bundle, or Serializable, which is not a simple process for beginners, and even seasoned developers don’t like them.

This is when Singletons come to the rescue.

Singletons are, as the name suggests, classes that are designed to generate only a single object instance, which allows multiple objects to have access to the same data, no matter when or how they access the Singleton. In Android, a common practice is to create and place a Singleton inside the project’s Application class. Doing so creates an app-wide accessible Singleton via a simple call to the Activity or Service getApplication() function.

The Singleton approach is simpler than having to configure a class for Intent transportation and makes for more readily accessible data. It is important to note that Singletons are not restricted to Android, and this option is widely used by Java developers.

However, there is one more, albeit biased, way of passing data around. Google encourages the use of Intent Extras. They provide an organized way of setting and getting data since Singletons follow the Object Oriented programming approach. The only issue is that they require some preparation to get going.

This third approach, which I prefer, is simple. I create a new class called AppData and only create public static variables that I expect to use across multiple Activities and Services. The beauty of this approach is that it is not limited to Activities and Services. Intent Extras and Singletons require access methods only available in those two Android classes. The AppData class, however, can be accessed by any and every Java class simply by invoking AppData.variableName.

Still, there is an issue with the AppData class approach; it breaks the laws of object-oriented programming. There is a reason Singletons are the preferred approach to passing data in a project; Singletons are classes that can be instantiated as objects. And since they are OOP compliant, they can be passed around as implementations of interfaces or even extensions to other classes. However, with AppData class approach you gain direct access to property, no code for instantiation, no code for prep, no code for management; the AppData class allows you to access data app-wide simply.

The rule of thumb here is only to use AppData with variables that are widely used in your project, such as an API Token that would be called in activities and web request classes.

Contributors

Faye-Lino Agli

Freelance Android Developer
Canada

Faye-Lino is a results-driven IT professional with a proven track record of implementing technology to drive business performance, productivity, and creativity. He's fluent in English and French. He has a lot of experience taking a client's idea making a fully scoped project and seeing it through. He communicates well and can work in a team or solo.

Show More

How to Know if Your App Is in the Background or Foreground

Android’s Activity lifecycle callbacks provide you with ample information about the state of your activities. But what about the application itself? Aren’t there onAppResume or onAppPaused functions? How does Android tell you when your app is in the background?

Android does not provide a way to clearly tell you if your app is no longer in the foreground (that is, one of your activities is visible to the user).

So, what is the workaround? Surprisingly, there are several; it’s a hot topic for Android. I’ve used this one for many years and it works well for me. It involves two simple steps:

First, create a custom base Activity class that you will use to override all the activities in your project. Second, in that base Activity, create a public static boolean flag (something like isAppInBackground). Next, override the onResume and onPause functions and simply update the flag appropriately: onResume → isAppInBackground = false; onPause → isAppInBackground = true;

Now, from anywhere in your project you can simply check BaseActivity.isAppInBackground to check the state of your app.

Contributors

Faye-Lino Agli

Freelance Android Developer
Canada

Faye-Lino is a results-driven IT professional with a proven track record of implementing technology to drive business performance, productivity, and creativity. He's fluent in English and French. He has a lot of experience taking a client's idea making a fully scoped project and seeing it through. He communicates well and can work in a team or solo.

Show More

Submit a tip

Submitted questions and answers are subject to review and editing, and may or may not be selected for posting, at the sole discretion of Toptal, LLC.

* All fields are required

Toptal Connects the Top 3% of Freelance Talent All Over The World.

Join the Toptal community.