I know this question is general but I am always face to face this problem.
My question is I can reach getResource() or getContext() in Activity but when I want to use a class without activity
example:
public class MapOverlay extends ItemizedOverlay
I can not reach getResources() or Context.
How can I do that anybody know any trick?
I usually do it the following way:
Create a class that extends Application, say MyApp.
Declare a private static Context context field
Declare a (static) getter for the context field
Initialize the field in onCreate(): context = this
Now context is available across all application via MyApp.context()
ItemizedOverlay in not extending android.content.Context.
You can create the construcor like
private Context mContext;
public MapOverlay(Context context){
this.mContext=context;
}
and then use the mContext field to call getResource() or getContext() methods.
Just expose a public method inside your MapOverlay that takes a Context.
public void setContext(Context context) {
mContext = context;
}
Related
I have a class that's inputting some data into SharedPreferences.
private static Context context;
context = MainActivity.getContext();
sp = (SharedPreferences) context.getSharedPreferences("currentData", Context.MODE_PRIVATE).edit();
SharedPreferences.Editor editor = sp.edit();
editor.putString("name", placeName);
editor.apply()
I set the context using a method in my MainActivity class:
public static Context getContext(){
return context;
}
However I keep getting a null object reference. Tried multiple solutions from stack overflow and can't overcome the issue.
Why is context returning null?
This is because MainActivity.getContext() is null try passing the context from MainActivity to your class.
public Context context;
public YourClass(Context context) {
this.context= context;
}
In MainActivity init it like this:-
YourClass yours = new YourClass(MainActivity.this);
And also avoid using static contexts it might cause memory leaks !!
Context is an abstract class whose implementation is provided by the
Android system
Context is provided to any Activity by the android system during runtime (Activity indirectly extends Context). You are trying to get Context from MainActivity class via static method, which will not work and will always return null:
context = MainActivity.getContext();
You should always get Context from an instance of Activity, not the class itself. You can do this easily by passing an instance of your current Activity to the constructor of your class. Then, you call getContext() on an INSTANCE of that Activity, not the Activity class itself.
Also, wanted to mention that your code is mostly anti-pattern. You should never store Context in static variables. I'd recommend you read more about Activity lifecycle in android and Context - these are fundamental knowledge.
You can get context statically throughout the application
please try below code:
In the Android Manifest file, declare the following.
<application android:name="com.xyz.MyApplication">
</application>
Use this class
public class MyApplication extends Application {
private static Context context;
public void onCreate() {
super.onCreate();
MyApplication.context = getApplicationContext();
}
public static Context getAppContext() {
return MyApplication.context;
}
}
Now you can call MyApplication.getAppContext() to get your application context statically.
You are getting the context from a static method in the class, that mean that method is called before the class is actually initialized. If there is no actual instance of the activity or if the OS haven't provide with context to the activity, then is null. The Activity has access to the contexto but after the Android underlining management initialized it, the class won't have the context by it self because it is there, if you notice Activities are never instantiated using the constructor because Android does it for you.
If you want to use a static method to having a nice syntax then the static method should be inside the class that use the shared preferences and should be passed from the activity, during any method of the Activity life cycle or when the user interacts with the ui (those listeners are set on the Activity life cycle).
class MyPreferences {
static void save(String toSave, Contex context) {
//TODO your operation here
}
}
And your activity:
public class MainActivity extends AppCompatActivity {
//Below is pseudo code, be careful on doing this precisely in the activity
#Override
onCreate() {
//TODO call super and setContentView
MyPreferences.save("foo", this);
}
}
It seems your problem is you are trying to make the other class to use the Activity, but in Android is the Activity that uses other classes
I'd like to get my string-array without extending Activity in my custom class. Is there a way to do this?
String[] foo_array = getResources().getStringArray(R.array.foo_array); will not work without extending Activity, so I need a work-around.
Pass the context to the constructor of custom class and use the same
new CustomClass(ActivityName.this);
Then
Context mContext;
public CustomClass(Context context)
{
mContext = context;
}
use the context
String[] foo_array = mContext.getResources().getStringArray(R.array.foo_array);
Also keep in mind
Do not keep long-lived references to a context-activity (a reference to an activity should have the same life cycle as the activity itself)
http://android-developers.blogspot.in/2009/01/avoiding-memory-leaks.html
Also check this
android getResources() from non-Activity class
Edit:
Change this
public class CustomClass(Context context)
{
}
To
public class CustomClass
{
Context mContext;
public CustomClass(Context context) // constructor
{
mContext = context;
}
}
try this,
Context context=getApplicationContext();
String[] foo_array = context.getResources().getStringArray(R.array.foo_array);
And, do not use Activity Context as that is tied to the Activity life cycle.
Update,
getApplicationContext() is from Context class. That means any thing extended Context have this method. This also means you will be able to use this from service or from other resources.
But, if you custom class do not extend Activity/context, you have to pass Context as parameter to use getApplicationContext()
if you declare your activity like this
myMethod(Activity activity) //this is bad
Bud if it is like following,
myMethod(Context context) //this is ok
but from above declaration do not pass Activity or Service Context as they have own life cycle. instead you will use getApplicationContext()
You need pass the Activity context to the Custom class.
private Context context;
public CustomClass(Context context)
{
this.context=context;
}
if you use numberpicker and pass String from sring xml then use this
np_Basic_Hight.setMinValue(0);
np_Basic_Hight.setMaxValue(71);
np_Basic_Hight.setDisplayedValues(getContext().getResources().getStringArray(R.array.hieght));
The deleteDatabase method needs a context in order to work. So in my class there is a context declared called ourContext. This class does not extend any other class like
Activity so I guess you could call it a helper class.
The only place in the class that uses context is the one method shown below that is called deleteData. and this calls the deleteDatabase method that needs a context to work.
ourContext.deleteDatabase(DATABASE_NAME);
Is it possible to not declare a context for the class in this situation? Can I use this for the context?
public class PlayGame {
private DbHelper ourHelper;
private final Context ourContext;
private SQLiteDatabase ourDatabase;
public PlayGame(Context c){
ourContext = c;
}
public void deleteData(){
ourContext.deleteDatabase(DATABASE_NAME);
}
No, Context is a class, you have to be derived from it to use this as a context. I suggest making deleteData take a Context as a parameter. I assume its going to be called from an Activity, Service, or something like a view that has a reference to a Context.
So, my first major application is almost coded and I'm doing optimizations on my code. The app works fine, but I'm not sure about my way of passing the context to other classes. I don't want to do it the wrong way. I stumbled upon articles and questions here in Stackoverflow about contexts and which is the right way to pass it to non-activity classes. I read the documentation as well, but being a Finn makes complicated tech speak even harder to understand.
So, a simple question. Is my way of passing my main activity's context to other (helper) classes correct? If not, where can I read more about better practice on these situations.
For example:
MainActivity.java
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle sis){
super(sis);
new Helper(MyActivity.this).makeMyAppAwesome();
}
}
Helper.java
public class Helper {
Context context;
Helper(Context ctx){
this.context = ctx;
}
public void makeMyAppAwesome(){
makeBaconAndEggsWithMeltedCheese(context);
}
}
Is this OK? It would be nice if someone could provide an easy to read article with examples on this subject.
You can do that using ContextWrapper, as described here.
For example:
public class MyContextWrapper extends ContextWrapper {
public MyContextWrapper(Context base) {
super(base);
}
public void makeMyAppAwesome(){
makeBaconAndEggsWithMeltedCheese(this);
}
}
And call the non activity class like this from an Activity
new MyContextWrapper(this);
It is usually in your best interest to just pass the current context at the moment it is needed. Storing it in a member variable will likely lead to leaked memory, and start causing issues as you build out more Activities and Services in your app.
public void iNeedContext(Context context) {...
Also, in any class that has context, I'd recommend making a member variable for readability and searchability, rather than directly passing or (ClassName.)this. For example in MainActivity.java:
Context mContext = MainActivity.this;
Activity mActivity = MainActivity.this;
I have passed context like this which solved my problem:
public class Utils extends ContextWrapper {
private final Context context;
public Utils(Context context) {
super(context);
this.context = context;
}
public void mymethod(){}
}
super(context); with ContextWrapper helped to make getBaseContext() and getApplicationContext() valid and this.context = context; captured context in variable which I can use wherever needed in methods.
Maybe alternatively you can just opt for using a constructor with this.context = context; and replace all occurrences of getApplicationContext() and getBaseContext().
Well, an even better way is to pass context directly to the method if using only few from a class for avoiding memory leaks.
You could also create a static instance reference to your MainActivity initialized in the onCreate() method
public class MainActivity extends AppCompatActivity {
public static MainActivity mMainActivity;
#Override
private onCreate(Bundle savedInstanceState){
//...
mMainActivity = this;
}
}
and call the context like this:
MainActivity.mMainActivity;
or write a method getInstanceOf() if it's clearer and/or you prefer using an accessor
MainActivity.getInstanceOf();
This strategy might provide you with some flexibility if you decide later that you would like to call an instance method contained in your main activity like so:
MainActivity.mMainActivity.myInstanceMethod();
Just a suggestion. Criticism is welcome and encouraged.
I'm defining a class that sets a Drawable attribute in an object. The problem is that I can't access the getResource().getDrawable(int resourceId) method unless I have some Context.
What I did was to send to that class an activity instance (let's call it "act") and then I did:
act.getResources().getDrawable(R.drawable.whellchair)
but, when executing that line it throws a NullPointerException.
When idea how to accomplish this?
I found the problem!
I'm using a singleton and I put the line accessing the "act" in a static method... how fool of me ...
Sorry and thank you Juhani for the comment :)
Pass that the application context to the constructor of your class. In the main application class you just get the context by invoking the getApplication() method if you need the a lifetime aware context or getApplicationContext() if you need a the context which is tied to the current process.
Example:
private Context ctx = getApplication();
... some code ...
MyClass myClass = new MyClass(ctx);
Your classes' constructor of course has to handle the context accordingly (i.e. setting a private member of type Context to the passed value) like this.
private Context ctx = null;
public MyClass(ctx) {
this.ctx = ctx;
}
Then you can use the context for whatever you need.