5

I am making a small musicplayer application in android , in which my main activity is using lots of static variables like this :-

 public class Fragmentactivity extends FragmentActivity {

         static ArrayList<String> s3=new ArrayList<String>();
        static ArrayList<String> s5=new ArrayList<String>();
        static ArrayList<String> songpaths=new ArrayList<String>();
         static ArrayList<String> alldirectorypaths=new ArrayList<String>();
         static ArrayList<String> internalpaths=new ArrayList<String>();
         static ArrayList<String> tempsongnames=new ArrayList<String>();
         static ArrayList<Bitmap> thumbnails=new ArrayList<Bitmap>();
         static int internal=0;
         static ArrayList<String> folderpaths=new ArrayList<String>();
    //my addtional code after it
    }

And I am accesing it in other classes like :-

  public class A{
    Fragmentactivity.songpaths.get(index);
    //and in  many other classes also i used it

I have made many static variables everywhere in my most of classes But now I learnt that this is not good practice for developing .

Should I continue with static or shoud I use getters/setters ?

Or if there are any other way to reuse variables...please suggests me.

Any help would be appreciated :)

Thanks in advance :)

KishuDroid
  • 5,411
  • 4
  • 30
  • 47
Animesh Mangla
  • 773
  • 7
  • 31
  • 2
    Side note: `Fragmentactivity` extending `FragmentActivity` seems not an happy naming choice to me. – moonwave99 Oct 23 '15 at 14:41
  • I will change it soon :) – Animesh Mangla Oct 23 '15 at 14:49
  • 1
    If your application works as intended, I'd recommend you take a look at [codereview.se], where you can ask the community for feedback on any & all aspects of your code (I'd recommend posting at least a whole class, not just snippets - the more context, the better!). – Mathieu Guindon Oct 23 '15 at 17:30

9 Answers9

8

Am not an Android expert. static have a special meaning that they can be shared across all the instances.

Hence if you are going to share them across multiple instances of them, just goahead with current way.

Should i continue with static or should i use getters/setters ?

Assuming you want shared variables, I'll mix them both

Fragmentactivity.getSongNames().get(index);

Update :

If you are not making multiple istances of it, just get rid of static and provide getter and setters to it. That is all you need.

public class Fragmentactivity extends FragmentActivity {

     private ArrayList<String> s3=new ArrayList<String>();

   ...
   ...
    public ArrayList<String> getS3() {
    return this.s3;
   }

   public setS3(ArrayList<String> input){
   this.s3= input;
  }

...
Suresh Atta
  • 120,458
  • 37
  • 198
  • 307
4

I see that you are trying to use static variables because songpaths, alldirectorypaths, internalpaths ..probably are values that should exist only in one instance to be accessed across your app. What you need is to use the singleton pattern.

the singleton pattern is a design pattern that restricts the instantiation of a class to one object. This is useful when exactly one object is needed to coordinate actions across the system. (wikipedia)

according to the book "Effective Java" of Joshua Bloch the most efficient way to implement a singleton is with Enums.

  public enum MusicPlayerContext{

    INSTANCE;

    public List<String> internalpaths = new ArrayList<String>();
    public List<String> alldirectorypaths= new ArrayList<String>();

  }

  public class MyActivity extends Activity{

      public void doSomething(){
         List<String> intPaths = MusicPlayerContext.INSTANCE.internalpaths; 
      }
  }

One more thing.. prefer to use interface for variable declaration (List) instead of implemtation (ArrayList< String >)

Luca S.
  • 1,132
  • 2
  • 16
  • 31
  • what is singleton pattern ?...can u elaborate please ? – Animesh Mangla Oct 23 '15 at 08:25
  • What is the benefit of using singleton? – Animesh Mangla Oct 23 '15 at 08:30
  • singleton restrict the instantiation of a class to one object. you will have only one instance of your class through your all program and you will be able to access it from everywhere. – Luca S. Oct 23 '15 at 08:33
  • What would be lifetime of singleton ? – Animesh Mangla Oct 23 '15 at 08:33
  • the same of your application – Luca S. Oct 23 '15 at 08:36
  • If my activity gets destoryed ..than after restarting of activity would they get reinitialised or previous values they will retian ? – Animesh Mangla Oct 23 '15 at 08:38
  • singleton are not related to the activities lifecycle but to Application lifecycle ...if your activity is destroyed they will keep the reference to your values. because of this avoid to store an activitycontext in singletons to avoid memory leaks. – Luca S. Oct 23 '15 at 08:45
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/93152/discussion-between-developer-and-luca-s). – Animesh Mangla Oct 23 '15 at 10:42
  • 1
    Singleton is a well-known [anti-pattern](https://en.wikipedia.org/wiki/Singleton_pattern)(second paragraph) that should be avoided unless absolutely necessary. It will add an entirely unnecessary global state to your app. – nukeforum Oct 23 '15 at 14:03
  • Anti-pattern doesn't mean that should always avoided. There is no black and white..if you use it properly it's a powerful and essential tool..it depends on the scenario.. in this case where he is storing only some paths that you want to be consistent through the application it would a safe and effective solution. – Luca S. Oct 23 '15 at 14:11
4

The main question to be answered in the design of the data model (in the context of the use static access to the variable) is - whether or not this variable to be associated with a class (if so then we use static modifier) or with the concrete instance of this class (and then this variable should be non-static).

Here are a lot of posts(link1, link2, link3) on advantages and disadvantages of using of the static variables in Java. This info is also relevant for the Android as well. And few more things to be mentioned here for Android:

  • it is strictly recommended to avoid creating of static reference to the Context and any of its subclasses because this is a direct source to the memory leak;
  • though static variables are not associated with concrete object and they will not be garbage-collected with it, but still their values will be cleared when application process is killed (by OS or user). So it is not appropriate for long term storing of valuable data.

With regard to possible alternatives of static access to the data, here are the most commonly used approaches:

  1. Singleton pattern. One of the simplest ways (came from usual Java):

    public class GlobalStorage {
        private static volatile GlobalStorage instance; // and drumroll - here we use static access again to make this data accessible everywhere in the app
        private GlobalStorage() { }
    
        public static GlobalStorage getInstance() {
            if (instance == null ) {
                synchronized (GlobalStorage.class) {
                    if (instance == null) {
                        instance = new GlobalStorage();
                    }
                }
            }
    
            return instance;
        }
    }
    
  2. Usage of Application class. Create a class subclassing the Application:

    public class CustomApp extends Application{
    private Storage mStorage;
    
         @Override
         public void onCreate() {
             super.onCreate();
    
             mStorage = new Storage();
         }
    
         public Storage getStorage(){
             return this.mStorage;
         }
    }
    

    and register it in Manifest as an attribute of <application> tag:

    <application
       android:name=".CustomApp"
       .... />
    

Though this approach is framework-defined it also is not a "silver bullet". Straight from documentation:

There is normally no need to subclass Application. In most situation, static singletons can provide the same functionality in a more modular way. If your singleton needs a global context (for example to register broadcast receivers), the function to retrieve it can be given a Context which internally uses Context.getApplicationContext() when first constructing the singleton.

Community
  • 1
  • 1
DmitryArc
  • 4,757
  • 2
  • 37
  • 42
  • @DmityArc your answer is prty good +1 for that ! and can u join me in a chat i need to ask two -three simple questions – Animesh Mangla Oct 23 '15 at 12:18
  • ok, lets continue discussion in [chat](http://chat.stackoverflow.com/rooms/93173/discussion-between-developer-and-dmitryarc) – DmitryArc Oct 23 '15 at 13:16
3

If you want to communicate 2 Fragments/Activities, then use a Bundle

ΦXocę 웃 Пepeúpa ツ
  • 47,427
  • 17
  • 69
  • 97
3

It will more or less depend on your functionality that you wish to achieve. Like do you want these variables to be shared across instances. Use of getter setters is no way related to declaring variable static . For any type of variables you can use getters and setters.

Other than accessors/mutators they have other advantages also.

Normally getters are declared to prevent your variables ( esp mutable ) from being exposed to outer world.

Setters are helpful if you don't want your client to update your variable directly.

For example consider the case of date variables

For date type variables, you may want to return a copy of your date variable to your client, not your own reference. Because client can misuse this reference or corrupt it. And while calling setter you may like to check the validity first of the date or its format whatever.

Community
  • 1
  • 1
SacJn
  • 777
  • 1
  • 6
  • 16
  • I think you could make an argument that it is pointless for a `public static` variable to have accessor methods. – nukeforum Oct 23 '15 at 14:06
3

static is thread unsafe, if you do not want to use get()/set() functions, you can use public to modify basic data types instead.

Define Point like this:

public class Point{
    public double x;
    public double y;
}

And then use Point like this :

Point p = new Point();
p.x = ;
p.y = ;

But, to Object data types, you would better use get()/set() functions, they are safe.

DmitryArc
  • 4,757
  • 2
  • 37
  • 42
nohup
  • 39
  • 1
3

This question has already been answered here.

Personally I would use a Singleton Pattern, it is very easy to implement and makes your code easier to test and easier to change in the future.

The point is that with static variables you have to write Fragmentactivity... everywhere in your client and you are coupling your client to this specific class.

Using a Singleton you could, f.i., introduce an interface and then in the future easily replace the Singleton with another one.

A Singleton implementation would also allow lazy initialization.

Community
  • 1
  • 1
atavio
  • 1,145
  • 13
  • 19
3

In native languages like C++ it's common practice to use getters (i = getCount()) instead of accessing the field directly (i = mCount). This is an excellent habit for C++ and is often practiced in other object oriented languages like C# and Java, because the compiler can usually inline the access, and if you need to restrict or debug field access you can add the code at any time.

However, this is a bad idea on Android. Virtual method calls are expensive, much more so than instance field lookups. It's reasonable to follow common object-oriented programming practices and have getters and setters in the public interface, but within a class you should always access fields directly.

So as android developer guide you should avoid so much use of getter/setter().

Reference : http://developer.android.com/training/articles/perf-tips.html

KishuDroid
  • 5,411
  • 4
  • 30
  • 47
  • Hi man can you please assist me in this question http://stackoverflow.com/questions/33298441/toolbar-alternative-of-splitactionbar ? – Moudiz Oct 23 '15 at 11:50
  • I just want to clarify, it is standard practice for **internal** field access to use the field reference rather than using the accessor methods. – nukeforum Oct 23 '15 at 13:57
2

For context, let's briefly talk about what static does. static is a keyword that changes the scope of a variable to global, persists its value across all instances, and makes its allocation of memory permanent for the lifetime of the application.

This has a few consequences:

  • The variable becomes unsafe for threaded environments
  • The variable, if public, can be accessed anywhere
  • The variable will never be cleaned by garbage collection

To more nicely perform what you're accomplishing with static, we can use an interface.

Make a new interface:

public interface FragmentActivityInterface {
  String getSongPath(int index);
  //etc...
}

Have your Fragment implement the interface:

public class Fragmentactivity extends FragmentActivity implements FragmentActivityInterface {

    static ArrayList<String> s3=new ArrayList<String>();
    static ArrayList<String> s5=new ArrayList<String>();
    static ArrayList<String> songpaths=new ArrayList<String>();
    static ArrayList<String> alldirectorypaths=new ArrayList<String>();
    static ArrayList<String> internalpaths=new ArrayList<String>();
    static ArrayList<String> tempsongnames=new ArrayList<String>();
    static ArrayList<Bitmap> thumbnails=new ArrayList<Bitmap>();
    static int internal=0;
    static ArrayList<String> folderpaths=new ArrayList<String>();
    //my addtional code after it

    @Override
    public String getSongPath(int index) {
        return songpaths.get(index);
    }

    //etc...
}

Make your other class require a FragmentActivityInterface:

public class A {
  private FragmentActivityInterface fragInterface;

  public A (FragmentActivityInterface fragInterface) {
    this.fragInterface = fragInterface;
  }
}

Finally, when you create the instance of your A class, you simply pass in your activity.

A foo = new A(this);

Now, anywhere in A where you want to get access to the FragmentActivity's members, just use fragInterface.getSongPath(0).

nukeforum
  • 1,284
  • 3
  • 16
  • 38
  • Sngleton pattern will be better .isnt it ? – Animesh Mangla Oct 23 '15 at 14:51
  • I would like to hear the rationale behind a fully static object being better. The Singleton pattern is widely considered to be an anti-pattern in the majority of cases. It puts an entire object in the `static` context. – nukeforum Oct 23 '15 at 14:53
  • Yes so it saves memory rite ?.and faster also ? – Animesh Mangla Oct 23 '15 at 14:57
  • That's the idea. If your Activity is ever paused or stopped, if its members are static, the memory can't be archived. Having unnecessary statics causes unnecessary bloat. – nukeforum Oct 23 '15 at 15:42