I have a Main class and another two classes named WebServicesClass and DynamicHeightAdpater.
I am creating an instance of DynamicHeightAdpater in WebServicesClass for which I need the context of MainActivity but I am not sure how to point it. The way by which I am calling throws a NullPointerException.
CODE :
MainActivity :
static Context context;
context = this.context;
WebServicesClass :
new DynamicHeightAdapter(MainActivity.context, 1, rowItems);
But it throws a null pointer exception and I am sure that it is due to the context cause I tried to print it and it threw NullPointer.
I would suggest you to take a look at the Android application class. You can store context there and retrieve it, when needed:
public class TestApplication extends Application {
private static Context mAppContext;
#Override
public void onCreate() {
super.onCreate();
mAppContext = getApplicationContext();
}
/**
* Returns the application's context. Useful for classes that need a Context
* but don't inherently have one.
*
* #return application context
*/
public static Context getAppContext() {
return mAppContext;
}
I suggest passing the Context to the WebServicesClass object in it's constructor, and having a member variable to keep it... something like
public class WebServicesClass
{
private Context mContext;
...
public WebServicesClass(Context c) // constructor
{
mContext = c;
}
void someOtherFunction()
{
new DynamicHeightAdapter(mContext, 1, rowItems);
}
}
Related
I am using Context object inside non-Activity, it is working perfectly but the problem is it shows warning
That is where I am using the context object
Here is the result of inspection
You can use WeakReferences for this case. something like this:
public class ContactsTask {
private WeakReference<Context> weakContext;
public ContactsTask(Context context){
weakContext = new WeakReference<>(context);
}
public void doSomething(){
if (weakContext!=null) weakContext.get() ... //return context without leaks
}
}
I have created one class that is extending Application class and using the static method to expose the contexts as follows. moreover i am using many util methods like checking internet connections e.c.t into this class.
Problem is i am not sure
how safe is to use following method to expose the application level context
would this create any memory leaks when i will use App.getAppContext() method
public class App extends Application {
private static Context mContext;
#Override
public void onCreate() {
super.onCreate();
mContext = this.getApplicationContext();
}
public static Context getAppContext() {
return mContext;
}
}
I've implemented a singleton class to avoid pass Activity as parameter to every method/constructor.
public class ApplicationContext {
private static class Holder {
private static final ApplicationContext INSTANCE = new ApplicationContext();
}
private ApplicationContext() {}
private Context mContext;
public static ApplicationContext getInstance(){
return Holder.INSTANCE;
}
public Context getContext(){
return Holder.INSTANCE.mContext;
}
public void setContext(Context mContext){
Holder.INSTANCE.mContext = mContext;
}
}
And in my initial activity, i set the context:
private void initializeObjects(){
ApplicationContext.getInstance().setContext(getApplicationContext());
}
The problem happens when i try to use context in a ProgressDialog:
#Override
protected void onPreExecute() {
pd = ProgressDialog.show(context, "", "Salvando Usuário");
}
Error message:
07-05 20:29:46.413 30930-30930/com.test.app E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.test.app, PID: 30930
android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
at android.view.ViewRootImpl.setView(ViewRootImpl.java:690)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:289)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:85)
at android.app.Dialog.show(Dialog.java:311)
at android.app.ProgressDialog.show(ProgressDialog.java:116)
Is a good practice to use a singleton like i've tried? What's wrong? If it's not, what is a good practice instead pass context/activity to every call?
Thank in advance.
For AlertDialogs you cannot use any context that isn't an Activity so use something like Activity.this or getActivity() if you are in a Fragment.
You can still use the Application global context to get colors and drawables and other stuff, but for example creating a view with this context the theme is ignored so try to use the Activity context as much as possible.
By the way if you want to have a singleton where you can access the context, you should extend the Application class in the ApplicationContext and override the method onCreate, along with adding this ApplicationContext class to your manifest Application element name. If you use that initializeObjects method and call it from the first activity what would happen to that context when you exit that activity?
So as an example:
public class ApplicationContext extends Application {
private Context mContext;
public static Context getContext(){
return mContext;
}
#Override
public void onCreate() {
mContext = this;
// you can initialize other stuff here if you want
}
}
// manifest
<application
android:name="com.example.ApplicationContext"
When the app is run, it always goes through the onCreate method of the Application class and it lives through the entire lifecycle of the app. But don't abuse it too much.
Android documentation for Application states:
There is normally no need to subclass Application. In most situations, static singletons can provide the same functionality [i.e. maintain global application state] in a more modular way. If your singleton needs a global context (for example to register broadcast receivers), the function to retrieve it can be given a Context which internally uses Context.getApplicationContext() when first constructing the singleton.
My request is: Can you explain, and provide code sample that implements the above suggestion for maintaining global state.
Note that there is already a suggestion that recommends subclassing Application:
How to declare global variables in Android?
Thank you.
Correction to StinePike's answer regarding context in the ApplicationState. In the code posted the context passed in to the application state is held on to. If the context passed in is an activity or similar unit then the activity would be leaked and prevented from being garbage collected.
The android documentation for the Application class states you should "internally use Context.getApplicationContext() when first constructing the singleton."
public class ApplicationState {
private Context applicationContext;
private static ApplicationState instance;
private ApplicationState(Context context) {
this.applicationContext = context.getApplicationContext();
}
public static ApplicationState getInstance(Context context) {
if(instance == null) {
instance = new ApplicationState(context);
}
return instance;
}
}
If I am not wrong your are trying to save global variables without extending Application. If so you can do two things
if you don't need any context then you ca simply use a class with static members like this
public class ApplicationState {
public static boolean get() {
return b;
}
public static void set(boolean a) {
b = a;
}
private static boolean b;
}
And if you need a context but you don't want to extend Application you can use
Public class ApplicationState {
private Context context;
private static ApplicationState instance;
private ApplicationState(Context context) {
this.context = context;
public static ApplicationState getInstance(Context context) {
if (instance == null) {
instance = new ApplicationState(context);
}
return instance;
}
public void someMethod(){}
}
So you can call some method like this
ApplicationState.getInstance(context).somemethod();
VPAdapter.java
public class VPAdapter extends PagerAdapter
{
public static String[] titles;
public final Context context;
public int[] scrollPosition;
JSONArray categories = null;
JSONArray newstype = null;
JSONObject json;
DatabaseHandler db = new DatabaseHandler(context)//error:The blank final field context may not have been initialized
...
}
DatabaseHandler.java
public class DatabaseHandler extends SQLiteOpenHelper {
public DatabaseHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
On VPAdapter.java I wanted to access DatabaseHandler anywhere, but there is problem with the constructor. What is the proper way I should write them?
You cannot pass a variable that was not initialize.
On your second line of the function you declare the context variable but you don't assign any value to it.
The last line should be written in the constructor of VPAdapter. The constructor should get a context variable. When you call your constructor you probably want to use the application context, but you might send also an activity (Activity inherit from context) but this is usually not recommended (But it really depends on your code)
Because your Context is null first initialize your context than you can pass that context to your database handler constructor.
Context context = getApplicationContext();
Or try below code
For example initialize your Context with your activity context.
Create constructor of your APAdapter class and call that constructor from your activity. Same way as you create for database handler.
public APAdapter(Context context) {
this.context = context;
}
than pass that context to your database handler.