I have an android app which encrypts and uploads various files to AWS. The boiler plate code for AWS is a singleton, and I use that throughout my app. I have an encryption class as well, and I am currently instantiating encryption objects in various places, encrypting the file, and passing it to the singleton instance of the AWS upload class.
I am wondering if this is the best approach? Should i make the instance of the encryption object static? And have just one instantiated, and then call the encrypt method from different classes? In some places it is recommended, in others people say using static can be dangerous? Or is there a better way than either of these options?
Should note the app works fine as is, but I am a self taught Android dev, and I am trying to get better, but none of the tutorials go into heaps of detail about things like this.
Static is not dangerous, it's to share operations that don't depend on instances of objects. Like the Math class.
Singleton pattern is for controlling instances of objetcs of some class. If you want an instance, and only one instance, you use singletons. Generally, people use it to get that instance at a global scope. I think the Application class would fit this.
I prefer to use dependency injection if I am working with a lot of service classes. Encryption is a service to me, but you have to do the mechanism for dependency injection, or use a framework, but this is overkill to your problem.
I would go for the static methods this time.
Creating a Singleton class or making your object static, both are good options if you have to use the method of a class on various places. It's better to have a static object then creating the same object again and again.
So according to me the "Singleton" class is the best option to make your code efficient, but if you want to go with a static method/class then there is no harm in it. Static can be dangerous in some situations, like when you have to assign different values and get different values in different situations. Then there is a chance you can get wrong value in wrong situation. But in your case it's fine.
Related
I am learning DI with Dagger2 and Hilt and I've got a question:
When creating android app I notice that I use lots of utility classes with static methods(i.e. a function that receives temperature in Celsius and return it in Fahrenheit). BUT, also I use a class (say NetworkUtils) with a static utility method for performing network call to get data from API (as what Android Nanodegree course's instructors were doing):
What I do is like:
class NetworkUtils{
public static String fetchCityName(double latitude, double longitude){
// code for API call
}
}
And now, while I am learning DI principles from Developer Docs, I notice that network calls are made in an instance class within an instance method and its parameters are injected using Dagger.
Why does this make difference from what I was doing?
I read that static methods make testing not easy, however, suppose I used DI like the docs shows,
Why do I have to instantiate a new object of the NetworkUtils whenever I need to perform API call while creating multiple instances is useless?
Also, the official docs says that our use of #Singleton annotation to set function scope (i.e. for a REST API call function) should be very rare, then:
Am I supposed to create instances for everything I need to use even tho it doesn't need to? (except for expensive object instantiation)
Eventually, could you please clarify the difference between a utility class and a normal class that I should not use static methods in it?
Thanks.
And now, while I am learning DI principles from Developer Docs, I
notice that network calls are made in an instance class within an
instance method and its parameters are injected using Dagger.
Why does this make difference from what I was doing? I read that static methods make testing not easy, however, suppose I used DI like
the docs shows,
I see two main reasons:
First, of course, is that the static calls make the code hard to test. But yes, there are some testing frameworks that can do the work for you and mock static calls. But whenever you are using them - it most likely means that you are doing something wrong or you are working with legacy code. This leads me to the second topic.
The idea of TDD - Test Driven Development is that you write the tests first, the code second. But the tests "are not important". Actually, the real result is the better code! The unit test just helps, but they are subproducts. Most of the time there is a high correlation between a good code and a testable code. When you have static calls and singletons it is easy for you to call this code from wherever you want. The result is that you stop thinking about design, about the real OOP principles - what is what. You do not think about extra objects, the relation between objects, etc. And you end up with a spaghetti code. Everything is tied to everything else.
Why do I have to instantiate a new object of the NetworkUtils whenever I need to perform API call while creating multiple instances
is useless? Also, the official docs says that our use of #Singleton
annotation to set function scope (i.e. for a REST API call function)
should be very rare, then:
You are saying something which is contradictory - "creating multiple instances is useless". Obviously creating an instance and not using a static call helps you to achieve better and testable code. Maybe you are wondering if it is a performance hit. Here I will quote.. maybe Martin Fowler... but in his book about Refactoring he is explaining that 9 out of 10 times the optimizations are just useless. You are overdoing it. You need to write good code. Then evaluate. Then if there is a need for optimization - you have the good code - the optimization will be relatively easy.
In your case - do not worry. Wrapping the network calls in instance classes will cause how many instances? 3? 5? It is not a problem when you evaluate the benefits.
About the Singleton - you do not need a shared state - so no need for a singleton. You will shoot yourself in the foot. You will keep things that can be garbage collected, add extra code for singleton creation, etc. Just plain object and that's all.
Am I supposed to create instances for everything I need to use even tho it doesn't need to? (except for expensive object
instantiation)
This is a huge question. You should read a few books and still will not know the answer. Try with Uncle Bob's Clean Code and also Martin Fowler's Refactoring. Then read a few articles of people who think that they are overdoing it and find the balance for yourself. In general, you should no be using "new" and any static calls.. But for example, there are a lot of discussions about how useful are really unit tests on Android and there are a lot of people who tend to go in the direction that you need mostly integration and End to End tests. I will not argue what is the right approach.
4. Eventually, could you please clarify the difference between a utility class and a normal class that I should not use static methods
in it?
Basically, you should not be using "Utility classes". Their idea is to wrap some code, which is used in many places, but there is no state involved. You do not need instance variables so the static methods were a good idea. But it will totally kill your testing. So in your case, you should make one type of class and if you need state - add, if you do not need state - just don't. Then you can call the classes whatever you want.
I am aware of the technique of extending the Application class to provide global storage. However in my case I am writing a class for a library function, so do not wish to force users of the class down this path. I have a requirement for some static class variables. I have seen passing references in StackOverflow that these might not be safe. However I've tried two different applications using the same class, and even when running both applications side by side on a Galaxy S3 in multi-window mode, the static class variables remain separate.
So, can someone with an in depth knowledge of Android internals confirm if this is safe or not.
If it is not safe, I can wrap the variables in a nested class and add them to a Serializable static HashMap, using the application package name as the key. This will force them to be safe. However if this is not necessary, then I'd rather not do it.
I have seen passing references in StackOverflow that these might not be safe.
They are not "safe" insofar as your process will be terminated from time to time, wiping out your static data members (and your custom Application, for that matter). Hence, static data members are good for a cache and not much else.
Within that scope, they are "safe".
You just need to make sure that this data is either stored somewhere persistent (e.g., file) or otherwise can be regenerated once the process is terminated and later is started up again. This is no different than with Application.
However I've tried two different applications using the same class, and even when running both applications side by side on a Galaxy S3 in multi-window mode, the static class variables remain separate.
Correct. Those are separate processes, with separate copies of your class and objects.
If your goal is to store persistant data across the twists and turns of the application lifecycle, then I would recommend not using static variables to do so. The obvious problem with this approach is that they could easily be garbage collected by the system when the operating system decides to reclaim memory (i.e. when the screen sleeps or a different application starts a memory-intensive task). I'm not sure what kind of data you are looking to "store", but I would recommend saving the state in SharedPreferences or an SQLiteDatabase instead.
I'm a little confused about what you're trying to do. You're trying to create a utility library in Java to be used by other applications? You're trying to create a whole Activity intended for use by other applications?
At any rate, as other posters have mentioned, applications can be killed at almost any time when resources become tight. There's simply no way to guarantee that static global values will remain resident in memory. You must provide a way to back it up on onPause() or onSaveInstanceState().
If you're writing a utility library, I presume that it returns some master object which holds all of its state. Add saveState(Bundle), restoreState(Bundle) methods to that object, and optionally saveToSharedPreferences() and restoreFromSharedPreferences() methods as well.
If it's an Activity you're writing, you're probably already familiar with the ways of saving state.
Me, I'm fond of combining the "singleton pattern" with shared preferences: https://stackoverflow.com/a/13673178/338479
You seem to have a deep misconception of how classes work.
Even if two classes are in the same package in two separate apps (by default) those apps run on separate VMs (i.e., processes). They literally have nothing to do with each other (as it should be, since otherwise you might get cross-app name collisions which is unacceptable).
What you're looking for is not a way to use static variables but a way to do inter-process communication (IPC). Android's Services are ideal for this, though there is a bit of a steep learning curve there.
Just started today to learn Android development, and I just can't find any info on how may I define a Helper class, or a collection of functions that will load globally and I'll be able to use them in any Activity that I create.
What I'm planning, is to create (at least for now) 2 functions that will be used almost in every activity, and would be a mess having to define the same functions in every activity.
Which would be the proper way to approach the above?
I want to throw out a quick note that you should not be putting functions in a global application class for this purpose. Generally what happens is that if you have shared functionality, you abstract that and put the code in:
Static methods
Another package
A library implementing the functionality against which you link your app
A content provider
You should explicitly not implement this functionality in the Application class. There are uses for extending the application, but doing so results in code smell and is a common antipattern for beginners. If you want a bunch of functionality which is shared in your app, a library is the perfect solution (even if it's just code you separate into another package). This encourages reuse and allows the code to be more cleanly segmented and tested.
It's common in Java to have either a class or pacakge of the form *.util for this.
(I'm guessing you come from something like a Rails world where this is the norm, since Ruby is much more metaprogramming oriented than Java, you generally use different tricks.)
This would be a static method in Java.
Java Static Methods
In a class Helper,
public static void DoSomething(){
}
Would be accessible from any class.
Example:
Helper.MyFunction();
I'm currently developing some Android Apps in a team and we've used 2 different approaches during the last months (one that i personally prefere, and the other that the other developer prefers).
Although so far the results are the same, this got me wondering...should we:
use AsyncTasks as private classes inside the Activities that use them.
or use AsyncTasks as separate public classes that receive the context of the activity
Are any of the approachs recommended by Google?
What does your experience say about this (advantages, disadvantages, problems)?
Inner classes are good for representing objects that are meant to be private or somehow intimately tied to the enclosing class. Occasionally there are technical reasons for using inner classes (e.g., simulating closures). They also cut down on namespace pollution.
One disadvantage of inner classes is that if they access private members (fields or functions) of the enclosing class, the compiler will generate accessor functions to those members. Language purists will argue whether this breaking of encapsulation is a Good Thing or a Bad Thing. The access functions add a bit of overhead to each access (which usually isn't a factor, but there it is). Another disadvantage is that it makes the source file more complex and therefore harder to manage. (I've occasionally been stung by editing a function in the inner class while thinking it was in the outer class, and vice versa.) Finally, inner classes tend not to be reusable, while separate classes can often be parameterized to have multiple uses.
These pros and cons are off the top of my head. I'm sure others will have additional thoughts.
UPDATE:
In this Google IO video the inner AsyncTask option is clearly marked as wrong option.
It doesn't matter, use what makes the most sense for your code. The important thing is to watch for an async task that is holding a reference on an activity after the activity has been destroyed, either implicitly as an inner class of the activity, or explicitly by being given the activity/context object.
I defined static variables in Activities in order to pass complex data between Activities.
Many people suggest not to use any static variables in Android. Some people suggest to store global data in a custom android.app.Application. I don't think there is any difference between static variable and custom Application.
I'd like to know your thoughts on static variables. Any suggestions?
Thanks.
Dear god don't do that. If you need to pass objects between activities, use a service.
Static variables are per definition global variables as they are scoped to a class instead of to an instance.
Depending on your design , it might perhaps it's better/cleaner/easier to have these global variables centralized instead of scattered over a plethora of classes.
Furthermore, in traditional software engineering, global variables are considered a bad thing, and that is correct, but when programming in a platform as Android where resources are scarce and optimal use of the resources to boost performance are of most importance so you should be developing with a totally different mindset.
Global variables don't have to be too bad in such a case.
Please note that the Android platform also provides a Service interface which could fit your need for sharing variables between Activities.