Static way to get 'Context' in Android?

前端 未结 19 2723
猫巷女王i
猫巷女王i 2020-11-21 06:36

Is there a way to get the current Context instance inside a static method?

I\'m looking for that way because I hate saving the \'Context\' instance eac

相关标签:
19条回答
  • 2020-11-21 07:01

    Here is an undocumented way to get an Application (which is a Context) from anywhere in the UI thread. It relies on the hidden static method ActivityThread.currentApplication(). It should work at least on Android 4.x.

    try {
        final Class<?> activityThreadClass =
                Class.forName("android.app.ActivityThread");
        final Method method = activityThreadClass.getMethod("currentApplication");
        return (Application) method.invoke(null, (Object[]) null);
    } catch (final ClassNotFoundException e) {
        // handle exception
    } catch (final NoSuchMethodException e) {
        // handle exception
    } catch (final IllegalArgumentException e) {
        // handle exception
    } catch (final IllegalAccessException e) {
        // handle exception
    } catch (final InvocationTargetException e) {
        // handle exception
    }
    

    Note that it is possible for this method to return null, e.g. when you call the method outside of the UI thread, or the application is not bound to the thread.

    It is still better to use @RohitGhatol's solution if you can change the Application code.

    0 讨论(0)
  • 2020-11-21 07:01

    If you don't want to modify the manifest file, you can manually store the context in a static variable in your initial activity:

    public class App {
        private static Context context;
    
        public static void setContext(Context cntxt) {
            context = cntxt;
        }
    
        public static Context getContext() {
            return context;
        }
    }
    

    And just set the context when your activity (or activities) start:

    // MainActivity
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        // Set Context
        App.setContext(getApplicationContext());
    
        // Other stuff
    }
    

    Note: Like all other answers, this is a potential memory leak.

    0 讨论(0)
  • 2020-11-21 07:02

    Rohit's answer seems correct. However, be aware that AndroidStudio's "Instant Run" depends on not having static Context attributes in your code, as far as I know.

    0 讨论(0)
  • 2020-11-21 07:03

    Assuming we're talking about getting the Application Context, I implemented it as suggested by @Rohit Ghatol extending Application. What happened then, it's that there's no guarantee that the context retrieved in such a way will always be non-null. At the time you need it, it's usually because you want to initialize an helper, or get a resource, that you cannot delay in time; handling the null case will not help you. So I understood I was basically fighting against the Android architecture, as stated in the docs

    Note: There is normally no need to subclass Application. In most situations, 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), include Context.getApplicationContext() as a Context argument when invoking your singleton's getInstance() method.

    and explained by Dianne Hackborn

    The only reason Application exists as something you can derive from is because during the pre-1.0 development one of our application developers was continually bugging me about needing to have a top-level application object they can derive from so they could have a more "normal" to them application model, and I eventually gave in. I will forever regret giving in on that one. :)

    She is also suggesting the solution to this problem:

    If what you want is some global state that can be shared across different parts of your app, use a singleton. [...] And this leads more naturally to how you should be managing these things -- initializing them on demand.

    so what I did was getting rid of extending Application, and pass the context directly to the singleton helper's getInstance(), while saving a reference to the application context in the private constructor:

    private static MyHelper instance;
    private final Context mContext;    
    
    private MyHelper(@NonNull Context context) {
        mContext = context.getApplicationContext();
    }
    
    public static MyHelper getInstance(@NonNull Context context) {
        synchronized(MyHelper.class) {
            if (instance == null) {
                instance = new MyHelper(context);
            }
            return instance;
        }
    }
    

    the caller will then pass a local context to the helper:

    Helper.getInstance(myCtx).doSomething();
    

    So, to answer this question properly: there are ways to access the Application Context statically, but they all should be discouraged, and you should prefer passing a local context to the singleton's getInstance().


    For anyone interested, you can read a more detailed version at fwd blog

    0 讨论(0)
  • 2020-11-21 07:07

    Kotlin

    open class MyApp : Application() {
        override fun onCreate() {
            super.onCreate()
            mInstance = this
        }
    
        companion object {
            lateinit var mInstance: MyApp
            fun getContext(): Context? {
                return mInstance.applicationContext
            }
        }
    }
    

    and get Context like

    MyApp.mInstance
    

    or

    MyApp.getContext()
    
    0 讨论(0)
  • 2020-11-21 07:11

    I use a variation of the Singleton design pattern to help me with this.

    import android.app.Activity;
    import android.content.Context;
    
    public class ApplicationContextSingleton {
        private static Activity gContext;
    
        public static void setContext( Activity activity) {
            gContext = activity;
        }
    
        public static Activity getActivity() {
            return gContext;
        }
    
        public static Context getContext() {
            return gContext;
        }
    }
    

    I then call ApplicationContextSingleton.setContext( this ); in my activity.onCreate() and ApplicationContextSingleton.setContext( null ); in onDestroy();

    0 讨论(0)
提交回复
热议问题