So it seems the following pattern in a class called ActivityClass:
private static class AsyncTaskLoader1 extends AsyncTaskLoader<E> {
........
}
private static class AsyncTaskLoader2 extends AsyncTaskLoader<F> {
.........
}
private class LoaderManager1 extends LoaderManager.LoaderCallbacks<E> {
private void onLoadFinished(AsyncTaskLoader1 loader, E data) {
//do stuff with data
//ok, now we need to start a asynchronous data load based on info we got back from 1st
ActivityClass.this.getLoaderManager().init(0, null, new LoaderManager2()).forceLoad();
}
}
private class LoaderManager2 extends LoaderManager.LoaderCallbacks<D> {
//...
}
This leads to the following runtime exception that looks something like:
java.lang.ClassCastException: E cannot be cast to F
at com.mycompany.myapp.ActivityClass$LoaderManager2.onLoadFinished
I assume this is because I am calling a second loader from the first one. If this is not possible, I assume there is a way to let the Activity know that data has been loaded so it can start a new AsyncTaskLoader from the UI thread, but I don't know how to do that. Could somebody enlighten me? Thanks.
So the issue ended up being that I was passing the same integer ID argument to initLoader for both the original call, AND the one in the first LoadManager's onLoadFinished method. I assume this was resulting in the result of the first loader to be returned to the wrong manager.
Related
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.
Why is the "environment" of FetchData not valid?
What content should be provided instead?
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(...);
tempDate.formatDateTime(this,tempJSONWeatherData.getLong("dt"), instead of this you can pass context of application, this refers on class FetchData
Note! This issue is now resolved, But still wonder How? Please explain?
These are my call back function which is being referenced in setter method of Custom adapter GridCartAdapter declaring in activity class.
gridCartAdapter.setOnDeleteCartItem(ProductListActivity.this);
gridCartAdapter.setOnAddCartItems(ProductListActivity.this);
here is defination for interface function in GridCartAdapter
public void setOnAddCartItems(OnAddCartItems onAddCartItems)
{
this.onAddCartItems = onAddCartItems;
}
public void setOnDeleteCartItem(onDeleteCartItem onDeleteCartItem) {
this.onDeleteCartItem = onDeleteCartItem;
}
so if I do same work in non activity class like this
gridCartAdapter.setOnDeleteCartItem((onDeleteCartItem)context);
gridCartAdapter.setOnAddCartItems((OnAddCartItems)context);
It gives an error of java.lang.ClassCastException: pk.wiseapps.wisemart.app.activity.SpecificProductActivity cannot be cast to pk.wiseapps.wisemart.app.onDeleteCartItem
Jus change this into my code
if(context instanceof onDeleteCartItem){
gridCartAdapter.setOnDeleteCartItem((onDeleteCartItem)context);
}
if(context instanceof OnAddCartItems){
gridCartAdapter.setOnAddCartItems((OnAddCartItems)context);
}
enter code here
I have a class that extends SwingWorker
public class PowerVCImageDeployer extends SwingWorker<Boolean,String>{
protected Boolean doInBackground() throws Exception {
PowerVCImageDeployer imageDeployer = new PowerVCImageDeployer();
imageDeployer.makeAConnection();
imageDeployer.makeNameIdMap();
// more code
return null;
}
public HashMap<String,String> makeNameIdMap(){
System.out.println("I am in make NameIdMap");
VolumeNameGetter idToName = new VolumeNameGetter();
ArrayList<String> list = (ArrayList<String>)volIDMap.keySet();
idNameMap = idToName.volNameGetter(list);
This is the trouble point. The control goes class idToName and it looks as if it doesn't come back. I have fully tested the class VolumeNameGetter using main method. The class is working good. There is no problem with it. So that looks as if once the control goes away from the SwingWorker it is unable to get it back ?? I have posted the output in the last line
System.out.println("The name Id Map is "+idNameMap);
System.out.println("Checking if the control comes back here");
return idNameMap;
}
}
The output of the code is
I am in make NameIdMap
This is troubling me a lot. Any help would be highly appreciated. Thanx in advance.
Debugger Output
and line number 127 is
return voulmeMap;
I need a class to get the artists, albums and tracks on the device, which I will then use JNI to call upon.
At the moment, in its barebones, the following causes a crash.
public class AndroidMediaLibray extends Activity {
public void getArtists() {
getContentResolver();
}
}
How do I get this to not crash?
The problem you have, is that you need to call getContentResolver() on a Context. If you call it in an Activity, you automatically call it on the Context of the Activity. But you (probably) never really start AndroidMediaLibrary. Please refer to the documentation of activities. If you want to have the DB call in an extra class, you may have a look at the following code. I have created a class with static methods. I just need to pass the context of my given Activity to that class. In your case that class might look like this:
public class AndroidMediaLibrary {
public static List<String> getArtists(Context context){
ArrayList<String> retVal = new ArrayList<String>();
ContentResolver resolver = context.getContentResolver();
// some more stuff here..
return retVal;
}
}
You may call that function from your MainActivity with:
List<String> myValues = DBUtils.someFunction(MainActivity.this);
I'm new to android and I need little help please. I want to pass data from an activity to a framelayout class, so I've implement a callback. On my activity I use an interface and setting the listener like this:
private OnCallStateListener onCallStateListener;
public interface OnCallStateListener{
int Data = 1;
void OnCallState(int wichAction)
}
public void setOnCallStateListener(OnCallStateListener listener){
onCallStateListener = listener;
}
private void dispatchTriggerEvent(int whichHandle){
if(onCallStateListener != null){
onCallStateListener.OnCallState(whichHandle);
}
}
And I use it like:
private onCallDisconnect(){
dispatchTriggerEvent(OnCallStateListener.DATA);
The dispatchTriggerEvent is executed but the problem is that the listener onCallStateListener is always null. what am I missing here?
Thanks!
It is null because you did not create an instance of the class. From what you have here you only have an interface. You would first need to create a class that implements that interface, and then say something like:
OnCallStateListener myVar = new OnCallStateListenerImpl();