Explain Codes LogoExplain Codes Logo

Getstring Outside of a Context or Activity

java
singleton
context
resources
Nikita BarsukovbyNikita Barsukov·Aug 26, 2024
TLDR

For accessing string resources without a Context, static access to constants is your friend. Declare them as static final fields in a class. Here is a baby-step guide:

public class AppStrings { public static final String CONSTANT_STRING = "FixedValue"; // Constants, they are like reliable friends, never change! }

Verification time! Use it anywhere in your app:

String value = AppStrings.CONSTANT_STRING; // I got it and you can't change me!

A word of caution, this approach is best suited for constant strings which don’t need Context for localization or runtime adjustments.

The dynamo: handling local resources

Dealing with local resources, such as string changing based on user's language settings? Then you need to embrace the dynamic approach.

public class MyApplication extends Application { private static MyApplication instance; public static MyApplication getInstance() { return instance; // It's me, Mario! } public static Resources getRes() { return instance.getResources(); // My resources are your resources! } @Override public void onCreate() { super.onCreate(); MyApplication.instance = this; // I am the one who gets created! } }

Next, declare MyApplication where it matters, in your AndroidManifest.xml:

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

Finally, call it a day! Access resources using MyApplication.getRes().getString(R.string.some_id) across your app.

Mind the pitfalls

While the road may seem bright and paved with the static application class, look out for the following potholes:

  • Check that your getInstance() is not returning a null. We all know what ensues otherwise, right? The dreaded NullPointerException.
  • Don't forget to import the right R class. It should match your package name to prevent 'symbol not found' errors.
  • Avoid using MyApplication.getInstance().getResources() from non-UI threads to avoid network issues.

Consider scalability and flexibility

A scalable and flexible approach to accessing resources is of paramount importance. Consider using dependency injection frameworks like Dagger or Hilt to maintain flexibility in accessing Context.

Systems vs. app resources

For system resources, like an "OK" button that'll be the same whatever language the user prefers, you can confidently use Resources.getSystem().getString(android.R.string.ok). But remember, system resources and your app's local resources are strangers. They never mix. So, always use a Context for accessing your app's particular strings, ensuring dynamic changes at runtime.

Global consistency and localization

Global access to strings using the earlier techniques will help maintain consistency and support localization. Make sure your dynamic resource access doesn’t take a short cut by hard-coding string values, or you’ll miss out on the goodies of internationalization.

Embracing limitations

Sometimes, passing a Context is the best way to go. If your static access method does not fit the bill, dynamically passing the Activity or Context to access resources is your ace in the hole.