When designing an Android Application, one of the important things to remember is the download size of your application. Huge download sizes discourage the users to download and install the application. The factor of size restriction becomes worse if you are designing a library, as developers will not want to bloat their application because of the size of your library.
Hence, to keep the library size less, it is important to bundle related functionality together while modularizing the other unrelated functionalities. This allows the developer integrating your library to pick and choose the functionality they want to avail from your library while keeping their application sizes in check.
1. Core: which will enable the basic chat flows like “Daily Quiz”, “Reminders” etc in the client’s application.
2. Travel: along with the basic chat flow the developers can also enable the functionality to make travel bookings using the Haptik UI flow, by integrating the Travel module of Haptik. (If transactions are needed, Payments module needs to be integrated as well)
3. Payments: Haptik also offers options to make Payments over its platforms, like “Recharge” for phones operators etc.
Modularizing the functionalities simultaneously increases the complexity of integrating the library. The developers using your library will have to keep in mind that they should initialize all the modules of the library before using it. Failing to do so, may cause the library to crash.
To solve the above problem one of the approaches is using REFLECTION.
What is Reflection?
In object-oriented programming languages such as Java, reflection allows inspection of classes, interfaces, fields and methods at runtime without knowing the names of the interfaces, fields, methods at compile time. It also allows instantiation of new objects and invocation of methods (Wikipedia).
Let’s understand Reflection in Java with a simple example:
Using Java Reflection you can check Java classes at runtime. Checking for classes is often the first thing you do when using Reflection. You can obtain the following information from the class:
- Class Name
- Class Modifies (public, private, synchronized etc.)
- Package Info
- Implemented Interfaces
- Annotations, plus a lot more information related to Java classes.
For a full list, you should consult the Doc for java.lang.Class.
Why use “reflection” to create objects instead of the “new” operator in Java?
– “new” operator is used to create objects as shown in the below example:
Here, the limitation is that if you use new operator there is no way to define the type of the object at runtime.
Let’s see how we can do this using Reflection:
Since the type of object needs to be created at the runtime, the availability of the class at the runtime needs to be checked:
You can explore more details about using reflection to get more properties of a class here.
What if the access to a constructor or a field or a method is private?
You can access a “private” method using:
So, you can check for the presence of the dependency in the build.gradle and internally initialize the class. If the class is not present you can also have a fallback mechanism.
To get access to the code for this project, visit:
We would love to know what you think about this approach and if there is any better way to tackle the problems of evergrowing sizes of mobile applications/SDKs. In our next blog, we will talk about some other things we did to reduce our android SDK size.