How to retrieve a context from a non-activity class?

27,938

Solution 1

If class B requires a Context to operate, then I don't see any problem having class A provide that to it (through a parameter on the play method, a parameter in a constructor, etc).

I don't think you are doing any poor OOP by providing class B the dependencies that it needs to do it's job.

Solution 2

This problem seem to arise a lot in Android development. One solution to obtaining a reference to a specific Context is subclassing the Application and grab a reference to the Context which you want.

public class MyApplication extends Application { 

private Context context;

@Override
public onCreate() {
  super.onCreate();
  this.context = getApplicationContext() // Grab the Context you want.
}

public static Context getApplicationContext() { return this.context; }
}

This solution however requires that you specify the name of your subclass in your manifest.

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

You can then use this anywhere in your application like this in non-activity classes.

MyApplication.getContext();  // Do something with the context! :)

Solution 3

I've answered also here.

You can do that using ContextWrapper, as described here.

For example:

public class MyContextWrapper extends ContextWrapper {

    public MyContextWrapper(Context base) {
      super(base);
   }

   public void someMethod() {
      // MediaPlayer.create(this, ...)
   }

}

Solution 4

Passing this around is a viable way of doing things, especially if this is the activity that creates the object in need of a Context. Sometimes, I'll put the Context into the constructor (like public MyObject(Context context){this.context = context;}), so that you don't need to send it every time. However, if your object is shared across multiple Activities, you should probably update the context it is looking at with the new Activity, though I haven't tested what happens if you use the old activity.

Share:
27,938
Admin
Author by

Admin

Updated on January 05, 2020

Comments

  • Admin
    Admin over 4 years

    I have found one answer that appears to say I should create a separate class and make a static MyApplication object and make a get method. Then any class can call MyApplication.get() to retrieve the context.

    Is there any other cleaner way? This is my situation:

    I have a class A and a class B. Class A contains an object from class B (let's call the object b). In class A I call, "b.play()". However, I get a null pointer exception because class B needs to pass a context to the MediaPlayer.create() method.

    Until now I threw together a hack and from class A I called.... "b.play(this)" and simply passed the context to B. However that is pretty ugly and looks like a bad use of OOP.

    Any thoughts?

  • Falmarri
    Falmarri almost 13 years
    I'll put the Context into the constructor [and then save it] That is a great way to cause a memory leak. though I haven't tested what happens if you use the old activity. Almost certainly an exception will be thrown, and you'll have leaked a context.
  • Admin
    Admin almost 13 years
    Hmm, if it's not frowned upon I think I will keep it, but pass the context within the constructor of class B to avoid passing the context a bunch of times. Thanks! Thus far this context business has been the most complicated part of Android development for me~
  • Admin
    Admin almost 13 years
    So passing through the method is better? How about the overhead involved in passing a context multiple times?
  • AlbeyAmakiir
    AlbeyAmakiir almost 13 years
    @Falmarri: Ah, yes. You should set the context to null when you intend to close it, just to be sure, though unreachable closed loops of references are candidates for garbage collection anyway.
  • Falmarri
    Falmarri almost 13 years
    @Google: There is practically 0 overhead in passing an object to an object. If your object's lifecycle is tied to the lifecycle of the context, then passing it is fine. But just beware you now have the potential to leak a context.
  • Falmarri
    Falmarri almost 13 years
    @AlbeAmakiir: though unreachable closed loops of references are candidates for garbage collection anyway The garbage collector is not that smart. Contexts are extremely complex objects. It's true they should eventually be garbage collected. However they most likely won't because contexts have a very specific lifecycle and are held in various places that the GC can't check.
  • Admin
    Admin almost 13 years
    How can I be sure the context isn't leaked?
  • AlbeyAmakiir
    AlbeyAmakiir almost 13 years
    @Falmarri: Held in places the GC can't check? That's something I have not heard before, and sounds completely bizarre. I also can't find anything to back that up. Similarly, the garbage collector should be that smart, unless they are ignoring part of the specification of java (which they might, because it's not quite Java anyway).
  • Falmarri
    Falmarri almost 13 years
    @AlbeyAmakiir: Native code can hold references to contexts. I'm pretty sure that if you pass a reference to a Context to native code, and then lose the reference in native code, your context has been leaked since the JVM has no idea what the native code is doing, and the GC can't assume that it's eligible for GC.
  • Falmarri
    Falmarri almost 13 years
    @Google: Don't hold strong references to contexts in objects whose lifecycle is greater than the lifecycle of the context.
  • jlindenbaum
    jlindenbaum almost 12 years
    This is actually extremely good OO and makes testing easier. Dependancy injection is a common design pattern.
  • ChuongPham
    ChuongPham almost 10 years
    Passing Context to the constructor is preferred as opposed to passing to each method within a class, since passing to a class method sometimes could result in a NullPointerException.
  • winklerrr
    winklerrr over 7 years
    You can't return an instance variable from a static function. You could refactor the context variable to be static - but that would be a potential memory leak.
  • Entalpi
    Entalpi over 7 years
    It should be possible since the unintialized value of a reference is just null but otherwise the variable should, as you say, be declared static. :)
  • winklerrr
    winklerrr over 7 years
    And a static context should be avoided due to its memory leak potential.
  • Suhas
    Suhas about 7 years
    And how do I get an instance of MyContextWrapper? I need to pass a Context to it which is what I am after in the first place.
  • user1510006
    user1510006 about 7 years
    @winklerrr What is your solution so ?
  • winklerrr
    winklerrr about 7 years
    @user1510006 pass a Context (could be your activity or the application context for example) to your non-activity class through its constructor. If you need to make sure, that you are working with the application context just call context.getApplicationContext() inside your constructor.