Vince VD
Vince VD

Reputation: 1581

How to pass context to a static method?

In my fragment i call a static method from another class

if (getActivity() != null) {
        Main.bindMusicService(getActivity().getApplicationContext(), position, songList);
}

Main class:

private static Context context;

private static ArrayList<Song> songList;

private static int songIndex;

public static void bindMusicService(Context c, int songPos, ArrayList<Song> songs){
    context = c;
    songIndex = songPos;
    songList = songs;
    /*mediaPlayerServiceIntent binds our connection to the MediaPlayerService. */
    if (!mServiceIsBound) {
        try {
            mediaPlayerServiceIntent = new Intent(c, MediaPlayerService.class);
            c.bindService(mediaPlayerServiceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
        } catch (Exception e) {
            Log.e("Main", "Service is not bound!");
        }
    }else{
        Main.mediaPlayerService.startActionPlay(context, songList, songIndex);
    }
    Log.i("Main","Service is bound!");
}

I get this warning for the context

Do not place Android context classes in static fields; this is a memory leak

What is the right way to send my arraylist, adapter position and context to another method which is in another class?

Upvotes: 0

Views: 2995

Answers (3)

Ashok Kumar
Ashok Kumar

Reputation: 1271

Another easy way could be , provide public getter method in application class which returns class instance member context and the context is initialised in oncreatw method of application class of your app.

Upvotes: 0

ASHKARAN
ASHKARAN

Reputation: 365

In Java, a static variable or constant will not be garbage collected. so it's better to avoid storing Context in a static variable

public static void bindMusicService(Context c, int songPos, ArrayList<Song> songs){
context = c;//remove this line

songIndex = songPos;
songList = songs;
/*mediaPlayerServiceIntent binds our connection to the MediaPlayerService. */
if (!mServiceIsBound) {
    try {
        mediaPlayerServiceIntent = new Intent(c, MediaPlayerService.class);
        c.bindService(mediaPlayerServiceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
    } catch (Exception e) {
        Log.e("Main", "Service is not bound!");
    }
}else{
    Main.mediaPlayerService.startActionPlay(context, songList, songIndex);
}
Log.i("Main","Service is bound!");
}

passing Context to a static method is fine, just DO NOT store it on the static variable.

mainly, I think you need a better way than passing Context to the methods, you can use the dagger, finally, if you have no choice it's better to use a Singleton pattern or a global Application Context which is traditional.

an example of dagger:

@Module
public class MainActivityModule {    
    private final Context context;

    public MainActivityModule (Context context) {
    this.context = context;
}

@Provides //scope is not necessary for parameters stored within the module
    public Context context() {
        return context;
    }
}

@Component(modules={MainActivityModule.class})
@Singleton
public interface MainActivityComponent {
    Context context();

    void inject(MainActivity mainActivity);
}

and then

MainActivityComponent mainActivityComponent = DaggerMainActivityComponent.builder()
.mainActivityModule(new MainActivityModule(MainActivity.this))
.build();

as an example of a Singleton pattern

private static SingletonDemo instance;

    public static SingletonDemo get() {
       if(instance == null) instance = getSync();
           return instance;
    }

    private static synchronized SingletonDemo getSync() {
       if(instance == null) instance = new SingletonDemo();
       return instance;
    }

    private SingletonDemo(){ 
        App.get();
    }

Application-level context:

public class App extends Application {
    private static App instance;
public static App get() { return instance; }

@Override
public void onCreate() {
  super.onCreate();
  instance = this;
   }
}

you have to define your application class on AndroidManifest.xml

<application 
    ...
    android:name="com.example.YourApplication" >
    ...
</application>

Upvotes: 0

CommonsWare
CommonsWare

Reputation: 1006614

Your problem is not sending the Context. Your problem is:

private static Context context;

If you are absolutely certain that you need something like that, replace it with:

private static Application context;

Adjust your method to take an Application as a parameter, and have your call to that method use getApplication() instead of getApplicationContext().

IOW, your code is reasonably safe — you are using the Application context — but the details of your code is making Lint nervous.

Upvotes: 3

Related Questions