动态加载滑动列表实现

本文介绍了一种动态加载滑动列表的策略,通过仅加载可见及预加载部分的UI节点来节省内存。在直播平台场景中,针对500个直播间图片的管理,采取了滚动时删除多余节点的方法,保持列表节点数恒定。同时,针对滑动过快导致的加载延迟,使用加载动画过渡。此外,优化了直播列表数据的获取,仅在切换标签时请求,并在客户端缓存90秒,减少不必要的刷新。未来计划进一步优化,按需从服务端获取数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

动态加载滑动列表

        采用了类似分片加载的策略,仅加载出当前可以看到的图片以及一定的预加载部分,随着滑动逐渐的加载出下边的内容,但大量的UI节点会造成内存的紧张,直播平台500个直播间的图片量不能导入所有贴图,大量的贴图残留在内存中会造成不必要的问题, 因此加载策略为仅显示当前看到的ITEM以及上下的预加载部分, 向上滑动删除下边多余的UI节点, 向下滑动删除上边多余的UI节点, 总之维持列表中的节点数为常量。

  略图

        如图所示是以上滑动过快的情况下显示的加载动画, 由于UI节点是异步动态加载的, 因此存在滑动过快造成加载不及时的情况,游戏中采用加载动画进行过度。此外由于直播列表数信息量较大, 因此在从服务端拉取直播列表信息上做了些优化, 仅在点击对应直播列表的标签页时从服务端进行数据请求, 数据回来后进行列表的显示,回来之前会有加载动画的显示,并且数据会在客户端进行90秒的缓存, 避免直播列表数据不必要的刷新造成的流量浪费。后期会进一步的优化,只从服务端返回显示需要的那一部分直播列表的信息, 在向下滑动时逐步加载出所有直播列表信息。

 

以下为代码实现样例


class ScrollViewAdapter(object):
    """
        自定义的滑动列表控件, 实现分片加载, 需要找UI制作列表节点两个Layout为父子关系,
        父Layout勾选剪裁, 子Layout与父Layout大小相同左上角为锚点, 都勾选交互。Item 锚点在中心
        加载采用定时加载的策略, 每隔一定时间加载一个Item, 滑动到没有加载完成的行, 
        就显示加载中的图标, 直到加载完预加载的内容。
    """

    # 列表的状态
    STOP = 0
    DRAG_MOVE = 1
    INERTIA_MOVE = 2
    BOUND_MOVE = 3

    ##########################################################################
    # 自定义滑动列表的初始化
    ##########################################################################

    def __init__(self, scroll_view, item_node, row_count, item_data_list, create_item_func):
        """
            @ scroll_view: 滑动列表控件
            @ item_node: Item Node
            @ row_count: 每行Item个数 
            @ item_data_list: 滑动列表Item的数据
            @ create_item_func 创建Item的接口
        """
        # 列表及其数据初始化
        self._scroll_view = scroll_view
        self._scroll_view.setVisible(True)
        self._scroll_size = self._scroll_view.getContentSize()
        self._scroll_inner = self._scroll_view.getChildren()[0]
        self._scroll_inner.setAnchorPoint(cc.Vec2(0, 1))
        self._scroll_inner.setVisible(True)
        self._scroll_inner.setSwallowTouches(False)
        self._scroll_org_pos = self._scroll_inner.getPosition()

        self._item_data_list = item_data_list
        self._item_dict = {}
        self._create_item_func = create_item_func
        self.item_count = len(self._item_data_list)

        # 设置Item的参数
        self._item_node = item_node
        self._item_size = item_node.getContentSize()
        self._x_extern = self._scroll_size.width / 4.0
        self._y_extern = self._scroll_size.height / 4.0

        self.BATCH_COL = int(row_count)
        self.BATCH_ROW = int(self._scroll_size.height / self._item_size.height)
        self.BATCH_NUM = self.BATCH_ROW * self.BATCH_COL

        self._up_index = 0                    # 显示的Item上索引
        self._down_index = 2 * self.BATCH_NUM - 1   # 显示的Item下索引
        self._item_up_index = 0  # 加载的Item上索引
        self._item_down_index = -1  # 加载的Item下索引
        self._has_load_index = -1  # 已经加载过的Item的索引

        # 列表事件监听
        self.last_tick_time = time.time()
        self._scroll_view.addTouchEventListener(self._on_scroll_view)

        # Item加载参数
        self.set_loading_speed(60)
        self.loading_widget = None
        self.loading_widget_size = cc.Size(self._x_extern / 2.0, self._x_extern / 2.0)
        self.last_loading_time = 0
        self.load_ani_time = 0
        self.is_up_loading_show = False
        self.is_down_loading_show = False
        self.stop_loading_index = 0  # 惯性滑动时停止加载的位置, 仅为美观

        # 列表状态机
        self.state_machine = {
            ScrollViewAdapter.STOP: self.on_stop,
            ScrollViewAdapter.INERTIA_MOVE: self.on_inertia_move,
            ScrollViewAdapter.BOUND_MOVE: self.on_bound_move,
        }

        # 列表滑动的相关参数
        self._move_state = ScrollViewAdapter.STOP
        self._acc_cur = 1000.0              # 当前加速度
        self._acc_inertia = 6000.0          # 惯性阻力值
        self._speed_inertia = 0.0           # 当前滑行速度
        self._min_speed = 200               # 最小速度
        self._max_speed = 1500              # 最大速度
        self._move_dis = 0.0                # 回弹距离
        self._speed_rebound = self._y_extern / 0.25

        # 列表滑动模式的控制参数
        self._inertia_stop_loading_mode = False  # 是否惯性滑动停止Item加载
        self.loading_done_time = 0.25  # 加载动画的显示时长
        self._is_swallow_touch = False  # Item 是否吃点击事件

        self.touch_pos = cc.Vec2(0, 0)
        self.start_time = time.time()

    def destroy(self):
        """
            清空数据
        """
        self.loading_widget = None
        self.change_m
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值