Android Studio context returning null - android

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

Related

Holding context, activity or views as member of a class is bad performance?

I have red somewhere that keeping views as members of an activity is bad performance, because each views is keeping a reference to its parent Context and it will fill up the heap. Is this true?
Imagine this activity:
public class MyActivity extends FragmentActivity{
private RelativeLayout mainLayout;
private LineraLayout menuLayout;
private FrameLayout tableLayout;
private Button buttonOk;
private Button buttonCancel;
#Override
protected void onCreate(Bundle bundle){
super.onCreate(bundle);
mainLayout = (RelativeLayout) findViewById(R.id.mainlayout);
// And inflating other views
}
}
And what about adapters?
public class MyAdapter extends BaseAdapter{
private MyActivity activity;
private ArrayList<MyObjects> myObjects;
public MyAdapter (MyActivity activity, ArrayList<MyObjects> myObjects){
this.activity = activity;
this.myObjects = myObjects;
}
}
Is this bad performance? Is it bad to pass an activity as a parameter instead of a Context? What if I want to access public methods from the parent MyActivity class from the adapter?
Non-Activity class
public MyDatabase{
private Context context;
private SQLiteDatabase db;
public MyDatabase(Context context){
this.context = context;
this.db = new DatabaseHelper(context).getWritableDatabase();
}
public Object getData(int id){
return db.query(params...);
}
public static class DatabseHelper extends SQLiteOpenHelper{
public DatabaseHelper(Context context){
super(context, "my_db", null, 1);
}
}
}
Why people are saying that when a class constructor expects a Context as a parameter, you should pass getApplicationContext() instead of and Activity?
To pass Activity instance to some method or store a reference to it somewhere is a bad practice because during configuration change Android creates a new instance of an activity and old one should be removed by garbage collector. But if someone holds a reference to an old Activity object it will not be collected by GC till reference to it exists. So memory leak occurs.
But in case of adapter constructor it's fully OK to pass activity instance because adapter lifecycle is coupled to activity lifecycle. Normally it will be garbage collected after activity.
getApplicationContext returns the context of the single, global Application object of the current process so it can be used safely throughout your application code.
It's not about bad performance, but related to possible memory leak. Pass getApplicationContext() instead of Activity is just to avoid potential memory leak.
There's nothing wrong for a activity to keep views as members, since the context of the view is activity. If activity doesn't hold the references, you need to invoke findViewById each time when you want to access the view, which will really impact the performance.About the adapter, it's still ok for you to pass activity not context.
Passing Activity's context is what you need at the end to access the public methods of your Activity because in any which ways if you use getApplicationContext() you will have to cast it to your Activity during method calls.
((MainActivity)context).getMyPublicMehtods() inside the non Activity class.
And for more details #makovkastar has defined it very well. :)

Access application context in a storage class in Android

I have an app on Android 4.0. It uses the PreferenceManager class to -- among other things -- let the user specify how many decimal places of a number to show.
mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
Generally I have no problem getting the app context in order to access the Preference Manager. My problem is that I have a class (let's call it Record) that isn't subclassing anything that has the app context; it's just a storage class, but it does have a field "NumDecPlaces". Right now, when I instantiate the class from within my app I just pass in the user's #dec places preference. It would be nice if Record could access the Preference manager directly. I suppose I could always instantiate Record with a pointer to the context from which it was created, but that's a lot to remember ;-)
So right now Record subclasses nothing. Any recommendations on what I can do to it to allow it to see the app context?
Thanks!
You could pass the Context object in the constructor. So whenever you try to use that class it will ask you pass a Context object and then use that to get SharedPreferences
For eg.
public Record(Context context)
{
mContext = context;
mPreferences = PreferenceManager.getDefaultSharedPreferences(mContext)
}
You can also extend a class with Application, which will be global to the whole application and you can set the context in that class as a member variable and that context will be global to the whole application
Eg. class A extends Application{......}
You can do #Apoorv's suggestion or you can create another class that specifically stores the application context.
public class ContextResolver {
private static Context context;
public static void setContext(Context context) {
if (context == null) {
throw new IllegalArgumentException("Context must not be null");
} else if (context instanceof android.app.Activity) {
context = androidContext.getApplicationContext();
} else if (context instanceof android.content.Context) {
context = androidContext;
}
}
public Context getContext() {
return context;
}
}
Now you need to call setContext() in the first activity that will be launched once.
public class MyFirstActivity extends Activity {
public void onCreate() {
ContextResolver.setContext(this);
}
}
Now you can retrieve the Context from any part of your code. So in your Record class you can just do this:
mPreferences = PreferenceManager.getDefaultSharedPreferences(ContextResolver.getContext());

Android: How do you access a string-array from strings.xml in a custom class?

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));

getSharedPreferences() is not recognized in the class extended from BroadcastReceiver

I like to use SharedPreferences in the class extended from BroadcastReceiver. But this method getSharedPreferences(prefName, MODE_PRIVATE); is not recognized. How can I retrieve SharedPreferences in the BroadcastReceiver class?
Thanks
you need a Context to retrieve the SharedPreferences. onReceive gives you the context
getSharedPreferences is a method of Context, your activity extends Context that is why you can use it as is.
If you want to use it somewhere else, you need a context. The easiest way is provided in this answer
Static way to get 'Context' on Android?
Step 1 : You add a class in AndroidManifest.xml
Step 2 : You create your class this way
public class App extends Application{
private static Context _context;
#Override
public void onCreate() {
super.onCreate();
_context = this;
}
public static Context getContext(){
return _context;
}
}
Step 3 : Whenever you need something with a context you do : App.getContext()
in your case App.getContext().getSharedPreferences()

How to obtain AssetManager without reference to Context?

I have a class that needs to obtain a reference to it's application's AssetManager. This class does not extend any sort of android UI class, so it doesn't have a getContext() method, or anything similar. Is there some sort of static Context.getCurrentApplicationContext() type of method?
To clarify: my class is intended to be used like a library, for other applications. It has no associated AndroidManifest.xml or control over the context which is calling it.
Create a subclass of Application, for instance public class App extends Application {
Set the android:name attribute of your <application> tag in the AndroidManifest.xml to point to your new class, e.g. android:name=".App"
In the onCreate() method of your app instance, save your context (e.g. this) to a static field named app and create a static method that returns this field, e.g. getApp():
This is how it should look:
public class App extends Application{
private static Context mContext;
#Override
public void onCreate() {
super.onCreate();
mContext = this;
}
public static Context getContext(){
return mContext;
}
}
Now you can use: App.getContext() whenever you want to get a context, and then getAssetManager() (or App.getContext().getAssetManager()).
I am not sure of the best answer to the OP question. However, I do know that you have to be very careful when using a static context as suggested in Android developer resources:
In the onCreate() method of your app instance, save your context (e.g. this) to a static field named app and create a static method that returns this field, e.g. getApp():
Using static contexts can leak to leaked memory issues, especially if the static context is used for references to views.

Categories

Resources