I guess this question is more about understanding context and how to use it properly. After having googled and "stackoverflowed" a lot I could not find the answer.
Problem:
when using DateUtils.formatDateTime I cannot use "this" as a context. The error message is as described in the title.
Application Info:
This is a simple weather app retrieving weather information via JSON and displaying it on the screen.
Activities:
- MainActivity.java
- FetchData.java
MainActivity: displaying the info
FetchData: getting JSON info from the API, formatting it and sending it back to MainActivity
I am using DateUtils.formatDateTime in the FetchData.java activity and using "this" as a context does not work. As from my understanding Context provided the "environment" (?) of where the method is being called.
Help is much appreciated. Thank you :)
Code:
private ArrayList<String> getWeatherDataFromJson(String forecastJsontStr) throws JSONException {
ArrayList<String> dailyWeatherInfo = new ArrayList<>();
int dataCount;
DateUtils tempDate = new DateUtils();
JSONObject weatherData = new JSONObject(forecastJsontStr);
JSONArray threeHourWeatherData = weatherData.getJSONArray(JSON_LIST);
dataCount = weatherData.getInt("cnt");
JSONObject tempJSONWeatherData;
for (int i = 0; i < dataCount; i++) {
tempJSONWeatherData = threeHourWeatherData.getJSONObject(i);
tempDate.formatDateTime(this,tempJSONWeatherData.getLong("dt"),
DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY |
DateUtils.FORMAT_ABBREV_ALL);
[more code here]
return dailyWeatherInfo;
}
Edit: I just realized I left out an important detail, namely this activity extends AsyncTask
. After some further research apparently you provide the context bei adding WeakReference
and then adding context in the constructor.
I added the following code:
private WeakReference<Context> contextWeakReference;
public FetchData (Content context) {
contextWeakReference = new WeakReference<>();
}
tempDate.formatDateTime(contextWeakReference.get(),tempJSONWeatherData.getLong("dt"),
DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY |
DateUtils.FORMAT_ABBREV_ALL);
This made the error disappear but I still don't understand why "this" doesn't work.
I am using DateUtils.formatDateTime in the FetchData.java activity and using "this" as a context does not work. As from my understanding Context provided the "environment" (?) of where the method is being called.
You're incorrect, Context is Android context which is (from documentation):
Interface to global information about an application environment. This is an abstract class whose implementation is provided by the Android system. It allows access to application-specific resources and classes, as well as up-calls for application-level operations such as launching activities, broadcasting and receiving intents, etc.
DateUtils.formatDateTime()
needs Context as one of its parameter. So, you need to pass a context.
Android Activity
is sub class of Context, so you can use this
(which refer to itself) as the context like the following:
public class MyActivity extends Activity {
...
protected void doSomething() {
// this refer to the MyActivity instance which is a Context.
DateUtils.formatDateTime(this, ...);
}
...
}
You need to pass the Context for every class that is not a Context subclass.
You can't use this
in AsyncTask because it's not a Context subclass. So, you need to pass the Context using WeakReference
to avoid Context leaking
, like the following:
private class AsyncTaskRunner extends AsyncTask<String, String, String> {
private WeakReference<Context> contextWeakReference;
public FetchData (Content context) {
contextWeakReference = new WeakReference<>();
}
private void doSomething() {
// We have the context from the WeakReference
Context context = contextWeakReference.get();
DateUtils.formatDateTime(context, ...);
}
}
Last, you don't need to create a DateUtils object when calling DateUtils.formatDateTime()
, so this isn't necessary:
DateUtils tempDate = new DateUtils();
tempDate.formatDateTime(...);
You can directly call it because it's a static method:
DateUtils.formatDateTime(...);