java - GreenDao - 自定义数据缓存无法正常工作

标签 java android caching greendao

我有一个具有 3 个一对多关系的实体

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

我想在手动创建的列表中总结这些数据(TotalData 只是结合了三个列表,以便于管理......)

private transient TotalData mTotalData;

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

我用 DaoSession.get...Dao().load(id) 加载我的实体...在第一次创建时一切正常,在第二次创建时,我的 mTotalData 已经存在并且包含空的子列表...为什么?

编辑:我的 TotalData 实现

TotalData 类中的所有数据都是实体!

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:流程示例

  • 我创建了一个 Activity 并加载了 ID 为 1 的实体 (DaoSession.load(1))
  • 我调用 getTotalData() => mTotalData 是正确的
  • 我转动屏幕并重新加载 ID 为 1 的缓存实体 (DaoSession.load(1))) => mTotalData != null 但它的所有字段是空的...因为它不是空的,如果我现在调用 getTotalData(),我得到一个 TotalData 对象,它没有更新它的值...它看起来像用空构造函数创建的对象(甚至不存在)

如果我将 isInitialised 变量添加到我的 TotalData 并在 getTotalData() 中检查此变量,我可能会解决这个问题......但仍然我不知道缓存是如何工作的以及为什么它不适用于我的自定义字段...

编辑3

非常感谢您的反馈,但我认为目前还不清楚到底是什么问题。

// 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;
}

我的工作:

  • 我调用 getWWorkoutObjects() 并获取所有正确的数据(加载 WWorkout 中的所有列表并且 sortedData 正确并填充
  • 我从不编辑数据!!!
  • 我重新创建 Activity (即转动屏幕)并获得正确的实体(WWorkout 中的所有列表都是正确的),但是 sortedData 中的 mObjects 是空的,但它已经存在了!!!为什么?

据我所知,mObjects 应该为 null 或者它应该保存来自实体的所有数据,但它不能有区别,因为唯一存在的构造函数是您在上面看到的构造函数(隐式加载实体的子列表)。

顺便说一句,init 函数之前是私有(private)的,我只是为了解决这个问题才公开它,我没有编辑任何数据来获得这种行为。

最佳答案

可能问题不在greendao的范围内。

请记住,例如在方向更改时,实际 Activity 会被销毁并重新创建。因此,您的 Activity 的私有(private)领域不能保证在方向改变时保持不变。您必须自己处理字段的正确状态。

你可以这样做:

  • 通过在 onCreate() 中初始化您的字段
  • 通过在 onPause() 中保存您的字段状态并在 onResume() 中恢复它

当然,您也可以防止在方向更改时重新创建您的 Activity 。有很多关于如何做到这一点的帖子。

尝试在 onCreate 方法中移动 DaoSession.load(1) 并在那里调用 getTotalData()。如果您已经这样做了,请发布您的 onCreate 方法。

除此之外,我建议对您的类(class)进行以下小改动。 尤其是在方法上使用 synchronized,因为如果变量在 synchronized block 内使用,但在 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);
    }
}

关于java - GreenDao - 自定义数据缓存无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20893236/

相关文章:

java - 如何处理倾向于一个apk的多个android项目

java - 是否可以使用 Twitter4j 库从特定用户获取 Twitter 的直接消息?

ruby - 缓存外部 API 的 API 设计

asp.net - 是否可以在多个 Web 服务器之间共享 System.Runtime.Caching 缓存对象?

java - 将字符串转换为数字并返回自然语言?

java - Java 中的通用 vector

android - 如何在 Android 设备本地的终端仿真器中运行 "adb shell"命令?

java - 将 Android 抽屉导航放在 ActionBar 顶部失败

android - android Activity 之间的自定义转换

php - 如何每天更新一次缓存(00 :00:00) in Laravel 5?