【对象池】未判断两个对象是否相同引起的问题

最近处理了一个几个版本之前遗留的问题,代码是一个离职的同事写的,测试发现了这个问题,但是不能稳定重现,所以一直没有修改。最近有玩家反馈过来,重现几率比较大,于是用玩家的号重现这个问题。

现象:战斗时会偶发性的缺少一些数据。具体表现是进战斗时有六个武将,但是显示出来会缺少一些武将。

经过多次调试,发现进战斗数据没有问题,只是显示出现了问题,显示的地方是取View代码里面的数据,并未修改。

代码逻辑:

1、先从对象池查看是否有空闲View,有就取出来使用,没有就新创建,将使用的对象放到队列里面保存下来,使用完成之后,根据这个队列将对象放回对象池。

2、根据自己的需求修改对象。

3、将使用后的对象放回对象池。

逻辑整体上没有什么问题,但是新加了个战斗模式之后,同事在第一步新增加了一个队列存放对象,在第三步,放回对象池时,将两个队列里面,相同的对象放回了对象池。这样下一次从对象池取数据的时候,有可能在需要两个对象时,取出来的是两个相同的对象。在修改数据时,第二个对象永远会覆盖第一个的数据引起bug。

代码逻辑大概是如下:

 public class TestData
    {
        public int TestNum;

        public void Dispose()
        {
            TestNum = 0;
        }
    }
    private List<TestData> m_testDataList1 = new List<TestData>();
    private List<TestData> m_testDataList2 = new List<TestData>();

    private Queue<TestData> m_testDataCacheList = new Queue<TestData>();

    public int TestA = 0;
    public int TestB = 0;

    private TestData ShowTestDataA;
    private TestData ShowTestDataB;
    private void OtherSystem()
    {
        EditorGUILayout.BeginVertical();
        if (GUILayout.Button("获取数据"))
        {
            ShowTestDataA = CreateData();
            //模拟取数据
            for (int i = 0; i < 2; i++)
            {
                ShowTestDataB = CreateData();
            }
             //模拟将数据加了两次
            m_testDataList1.Add(ShowTestDataA);
            m_testDataList1.Add(ShowTestDataB);

            m_testDataList2.Add(ShowTestDataA);
            m_testDataList2.Add(ShowTestDataB);
            if (ShowTestDataA == ShowTestDataB)
            {
                Log.Error("如果取出来两个对象地址相同+++++++++++++++");
            }
        }
        TestA = EditorGUILayout.IntField("TestA:", TestA);
        TestB = EditorGUILayout.IntField("TestB:", TestB);

        if (GUILayout.Button("修改数据"))
        {
            ChangeData(ShowTestDataA, TestA);
            ChangeData(ShowTestDataB,TestB);
        }
        if (GUILayout.Button("回收数据"))
        {
            //模拟将同一个对象添加到对象池。
            for (int i = 0; i < m_testDataList2.Count; i++)
            {
                DisposeData(m_testDataList2[i]);
            }
            for (int i = 0; i < m_testDataList1.Count; i++)
            {
                DisposeData(m_testDataList1[i]);
            }
            m_testDataList1.Clear();
            m_testDataList2.Clear();
        }
        if (GUILayout.Button("清除缓存"))
        {
            m_testDataList1.Clear();
            m_testDataList2.Clear();
            m_testDataCacheList.Clear();
        }
        if (ShowTestDataA != null)
        {
            GUILayout.Label("ShowTestDataA:" + ShowTestDataA.TestNum.ToString());
        }
        if (ShowTestDataB != null)
        {
            GUILayout.Label("ShowTestDataB:" + ShowTestDataB.TestNum.ToString());
        }
        EditorGUILayout.EndVertical();
    }
    private void ChangeData(TestData data,int num)
    {
        if (data == null)
        {
            return;
        }
        data.TestNum = num;
    }
    private void DisposeData(TestData data)
    {
        if (data ==null)
        {
            return;
        }
        data.Dispose();
        if (m_testDataCacheList.Contains(data))
        {
            Log.Error("存进来的对象相同");
        }
        m_testDataCacheList.Enqueue(data);
    }
    private TestData CreateData()
    {
        if (m_testDataCacheList.Count > 0)
        {
            TestData data = m_testDataCacheList.Dequeue();
            return data;
        }
        else
        {
            TestData data = new TestData();
            return data;
        }
    }

因为对象池可能将一个对象存入两次,导致取出来时可能会将同一个对象的地址分配给两个对象,修改数据时出现问题。

修改:在将对象放入对象池时,判断一下对象是否相同。

猜你喜欢

转载自blog.csdn.net/qq_33461689/article/details/124930520