Question

I have an entity with 3 one-to-many relations

private List<Data1> Data1;
private List<Data2> Data2;
private List<Data3> Data3;

and I want to summurize this data in a manually created list (TotalData just combines the three lists, for easier management...)

private transient TotalData mTotalData;

public TotalData getTotalData()
{
    if (mTotalData == null)
        mTotalData = new TotalData(getData1(), getData2(), getData3());
    return mTotalData;
}

I load my entity with DaoSession.get...Dao().load(id)... On first creation everything works fine, on second creation, my mTotalData already exists and contains empty sublists... Why?

EDIT: my TotalData implementation

All data in the TotalData class are Entities!

public class WWorkoutObjectList
{
    private ComparatorWWorkoutObject mComparator = new ComparatorWWorkoutObject();
    private List<WWorkoutObject> mObjects = new ArrayList<WWorkoutObject>();

    public WWorkoutObjectList(List<WExercise> wExercises, List<WCardio> wCardio, List<WPause> wPause)
    {
        init(wExercises, wCardio, wPause);
    }

    public void init(List<WExercise> wExercises, List<WCardio> wCardio, List<WPause> wPause)
    {
        synchronized (mObjects)
        {
            mObjects.clear();
            for (int i = 0; i < wExercises.size(); i++)
                mObjects.add(new WWorkoutObject(wExercises.get(i)));
            for (int i = 0; i < wCardio.size(); i++)
                mObjects.add(new WWorkoutObject(wCardio.get(i)));
            for (int i = 0; i < wPause.size(); i++)
                mObjects.add(new WWorkoutObject(wPause.get(i)));
            sort();
        }
    }

    public void add(WWorkoutObject wObject)
    {
        synchronized (mObjects)
        {
            mObjects.add(wObject);
            sort();
        }
    }

    public int size()
    {
        return mObjects.size();
    }

    public WWorkoutObject get(int index)
    {
        return mObjects.get(index);
    }

    public WWorkoutObject remove(int index)
    {
        return mObjects.remove(index);
    }

    // ----------------
    // Hilfsfunktionen
    // ----------------

    public WExercise getNextExercise(int currentIndex)
    {
        synchronized (mObjects)
        {
            for (int i = currentIndex + 1; i < mObjects.size(); i++)
            {
                if (mObjects.get(i).isWCardio())
                    return null;
                if (mObjects.get(i).isWExercise())
                    return mObjects.get(i).getWExercise();
            }
        }
        return null;
    }

    public int getFragmentCount()
    {
        int counter = 0;
        synchronized (mObjects)
        {
            for (int i = 0; i < mObjects.size(); i++)
            {
                if (mObjects.get(i).isFragmentObject())
                    counter++;
            }
        }
        return counter;
    }

    public WWorkoutObject getFragmentObject(int fragmentIndex)
    {
        if (fragmentIndex < 0 || fragmentIndex >= mObjects.size())
            return null;

        int counter = 0;
        synchronized (mObjects)
        {
            for (int i = 0; i < mObjects.size(); i++)
            {
                if (mObjects.get(i).isFragmentObject())
                {
                    if (counter == fragmentIndex)
                        return mObjects.get(i);
                    counter++;
                }
            }
        }
        return null;
    }

    public List<WWorkoutObject> getFragmentsObjectsList()
    {
        List<WWorkoutObject> list = new ArrayList<WWorkoutObject>();
        synchronized (mObjects)
        {
            for (int i = 0; i < mObjects.size(); i++)
            {
                if (mObjects.get(i).isFragmentObject())
                    list.add(mObjects.get(i));
            }
        }
        return list;
    }

    public List<WWorkoutObject> list()
    {
        return mObjects;
    }

    // ----------------
    // private Funktionen
    // ----------------

    private void sort()
    {
        Collections.sort(mObjects, mComparator);
    }
}

Edit2: Flow example

  • I create an activity and load my Entity with id 1 (DaoSession.load(1))
  • I call getTotalData() => mTotalData is correct
  • I turn the screen and reload my now CACHED Entity with id 1 (DaoSession.load(1))) => mTotalData != null but all fields of it are empty... Because it is not null, if I now call getTotalData(), I get a TotalData object that did not update it's values... It looks like an object that was created with an empty constructor (which does not even exist)

I may solve that if I add a isInitialised variable to my TotalData and check this variable in getTotalData()... But still I don't know how the caching is working and why it's not working with my custom field...

Edit3

I am thankful for the feedback, but I think it's still not clear what exactly the problem is.

// Activity onCreate
public void onCreate(Bundle savedInstanceState)
{
    WWorkout workout = DaoSession.load(1);
    WWorkoutObjectList sortedData = workout.getWWorkoutObjects();
}

// Dao Entity custom function
public WWorkoutObjectList getWWorkoutObjects()
{
    // I make sure, with calling the getter functions, that I load all sub entities before creating the list!!!
    if (wWorkoutObjectList == null)
        wWorkoutObjectList = new WWorkoutObjectList(getWExercise(), getWCardio(), getWPause());
    return wWorkoutObjectList;
}

What I do:

  • I call getWWorkoutObjects() and get all correct data (all lists in WWorkout are loaded and sortedData is correct and filled
  • I NEVER edit data!!!
  • I recreate the activity (i.e. turn the screen) and get a correct entity (all lists in WWorkout are correct), BUT mObjects in sortedData is empty, but it exists already!!! Why?

As far as I understand, mObjects should be null or it should hold all data from the entity, but it can't differ, because the only constructor that exists is the one you can see above (that implicitly loads the sub lists of the entity).

Btw, the init function was private before, I only have made it public for a workaround and I did NOT edit any data to get this behaviour.

Was it helpful?

Solution

Probably the problem doesn't lie within the scope of greendao.

Remember that for example on orientation change the actual activity gets destroyed and recreated. Thus a private field of your activity is not garanteed to stay the same on orientation change. You have to take care of the correct state of your fields yourself.

You can do that:

  • by initializing your fields in onCreate()
  • by saving the state of your fields in onPause() and restoring it in onResume()

Of course you can also prevent your activity from being recreated on orientation changes. There are a lot posts about how to do that.

Try to move DaoSession.load(1) in the onCreate-method and call getTotalData() there as well. If you already have done that, please post your onCreate-method.

On top of that I'd recommend the following minor changes to your class. Especially using synchronized on the methods, because there may be strange behaviours if variables you use inside the synchronized block, but that are defined outside the block.

public class WWorkoutObjectList
{
    private ComparatorWWorkoutObject mComparator = new ComparatorWWorkoutObject();
    private List<WWorkoutObject> mObjects = new ArrayList<WWorkoutObject>();

    public WWorkoutObjectList(List<WExercise> wExercises, List<WCardio> wCardio, List<WPause> wPause)
    {
        init(wExercises, wCardio, wPause);
    }

    public synchronized void init(List<WExercise> wExercises, List<WCardio> wCardio, List<WPause> wPause)
    {
        mObjects.clear();
        if (wExercises != null) {
            for (WExercise we : wExercises) {
                mObjects.add(new WWorkoutObject(we));
            }
        }
        if (wCardio != null) {
            for (WCardio wc : wCardio) {
                mObjects.add(new WWorkoutObject(wc));
            }
        }
        if (wPause != null) {
            for (WPause wp : wPause) {
                mObjects.add(new WWorkoutObject(wp));
            }
        }
        sort();
    }

    public synchronized void add(WWorkoutObject wObject)
    {
        mObjects.add(wObject);
        sort();
    }

    public int size()
    {
        return mObjects.size();
    }

    public WWorkoutObject get(int index)
    {
        return mObjects.get(index);
    }

    public synchronized WWorkoutObject remove(int index)
    {
        return mObjects.remove(index);
    }

    // ----------------
    // Hilfsfunktionen
    // ----------------

    public synchronized WExercise getNextExercise(int currentIndex)
    {
        for (int i = currentIndex + 1; i < mObjects.size(); i++)
        {
            if (mObjects.get(i).isWCardio())
                return null;
            if (mObjects.get(i).isWExercise())
                return mObjects.get(i).getWExercise();
        }
        return null;
    }

    public synchronized int getFragmentCount()
    {
        int counter = 0;
        for (WWorkoutObject wo : mObjects)
        {
            if (wo.isFragmentObject())
                counter++;
        }
        return counter;
    }

    public synchronized WWorkoutObject getFragmentObject(int fragmentIndex)
    {
        if (fragmentIndex < 0 || fragmentIndex >= mObjects.size())
            return null;
        int counter = 0;
        for (WWorkoutObject wo : mObjects)
        {
            if (wo.isFragmentObject())
            {
                if (counter == fragmentIndex)
                    return mObjects.get(i);
                counter++;
            }
        }
        return null;
    }

    public synchronized List<WWorkoutObject> getFragmentsObjectsList()
    {
        List<WWorkoutObject> list = new ArrayList<WWorkoutObject>();
        for (WWorkoutObject wo : mObjects)
        {
            if (wo.isFragmentObject())
                list.add(wo);
        }
        return list;
    }

    public synchronized List<WWorkoutObject> list()
    {
        ArrayList<WWorkoutObject> result = new ArrayList<WWorkoutObject>();
        for (WWorkoutObject wo : mObjects)
            result.add(wo);
        return result;
    }

    // ----------------
    // private Funktionen
    // ----------------

    private void sort()
    {
        Collections.sort(mObjects, mComparator);
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top