0

Here is my method:

public Cursor rawQuery(String sql, String[] selectionArgs) {
    try {
        return m_db.rawQuery(sql, selectionArgs);
    } catch (SQLiteException e) {
        reportException(Context.getApplicationContext(), e);
        return null;
    }
}

Android Studio (3.5.3) complains saying

Non-static method getApplicationContext() cannot be referenced from a static context.

I don't see any static context here. rawQuery is a perfectly good class method of a class which is a wrapper around SQLiteDatabase to save me having to check for exceptions on every call. The exception checks are needed because it's accessing a public database and some other process may have modified it in such a way that my operation fails (for example by dropping one of my tables). It is (currently) only created and its methods called from an Activity. Of course I could pass the calling activity's context, but this is clumsy since it isn't needed most of the time and IMHO it's very poor programming style to include extra arguments in the methods of a wrapper class.

reportException does what its name says and writes a log file or displays a Notification or a Toast, depending on circumstances, and all of these need a context.

I've seen suggestions on the net to create a static instance of a subclass of Application to cache the application context. As commenters have pointed out, this doesn't always work if you need the application context in a class constructor (or anything which is called from one), but I don't expect to do this. My wrapper class is created as needed when I want to access the database. However I'm not sure if tha Application subclassing trick works if I open a database in a background server which may get kicked out of memory when not active and later restarted by the OS. It may be that the only solution is to cache the creator's context in the constructor of the wrapper class: this only requires passing the context once. However I don't much like the idea of keeping a copy of the passed context: it looks inelegant and a potential problem with garbage collection since I have to take care not to use the cached context when creating anything persistent..

However I still don't see Android Studio's justification for complaining in the case shown. I tried removing all the calls to rawQuery and it still complains, so it isn't walking the call tree to look for a non-static context. It looks as if it may be complaining if getApplicationContext is used in any class which isn't a subclass of Activity, which certainly isn't justified.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268
  • In short: you need a `Context` instance to call a non-static method. You cannot call `getApplicationContext()` with the class name. – Code-Apprentice Dec 12 '19 at 21:37
  • "I don't see any static context here. " The static context is the class name `Context` in `Context.getApplicationContext()`. – Code-Apprentice Dec 12 '19 at 21:38

1 Answers1

1

I don't see any static context here.

The "static context" referred to by the error message is the way you are calling the method: Context.getApplicationContext(). Since you are using the Context class name, this counts as a "static context". You need a Context instance in order to call getApplicationContext().

Of course I could pass the calling activity's context, but this is clumsy since it isn't needed most of the time and IMHO it's very poor programming style to include extra arguments in the methods of a wrapper class.

Yes, I agree that you should keep your argument list as trimmed down as possible. You say that this method is a wrapper around SQLiteOpenHelper which requires a Context as one of its constructor parameters. So presumably your own constructor takes a Context to pass to the wrapped SQLiteOpenHelper instance. One solution is to keep that Context as a field in your class. Then you can just use this.context.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268