当前位置: 首页 > 知识库问答 >
问题:

图表库在滚动时滞后

向修谨
2023-03-14

我刚刚实现了库图表(https://github.com/danielgindi/Charts)在tableview中,当我的图表包含大量数据时,我在滚动过程中遇到了很大的延迟。

我在ChartTableViewCell中有一个html" target="_blank">方法,我在其中根据从我的视图控制器传递和调用的数据绘制图表。

func updateCell(chartData: ChartData) {

    DispatchQueue.global(qos: .background).async {
        print("This is run on the background queue")
    self.readings = (readings != nil) ? readings!.readings : []
        self.period = period

        if (chartData.isKind(of: LineChartData.self)) {
            data.lineData = chartData as! LineChartData
        }
        else if (chartData.isKind(of: BarChartData.self)) {
            data.barData = chartData as! BarChartData
        }
    }

    DispatchQueue.main.async {
    self.chartView.data = data
    }
}

在我的tableViewController中,我在解析数据后调用函数:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let meta = chartMetas[indexPath.row]
        let cell = tableView.dequeueReusableCell(withIdentifier: "chartCell", for: indexPath) as! ChartTableViewCell
        cell.readings = currentReadings
        cell.updateCell()

        return cell
    }

我错过了什么?因为滚动时视图滞后得很厉害。

更新:

按照建议,我尝试在视图控制器中准备图表数据并将其传递给单元格。然而,这似乎是可重用单元格中的问题,当我滚动并有新单元格进入屏幕时会出现延迟。我该如何解决这个问题?这很烦人。

更新2:看起来图表不应该在tableview中使用。。。https://github.com/danielgindi/Charts/issues/3395

共有3个答案

方焱
2023-03-14

尝试在将所有图表数据传递给单元格之前准备好所有图表数据。我的意思是让您所做的所有事情都在您的tableViewController中的updateCell()func中,可能在viewddLoad中,并将生成的图表数据传递给数组。

然后在tableView(tableView:,cellForRowAt indexPath:)中,只需将先前生成的数据传递给单元格。

因此,updateCell函数应该如下所示:

func updateCell(lineChartData: LineChartData) {
    // SET DATA AND RELOAD
    chartView.data = lineChartData
    chartView.fitScreen()
}

还有你的桌子

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let meta = chartMetas[indexPath.row]
    let cell = tableView.dequeueReusableCell(withIdentifier: "chartCell", for: indexPath) as! ChartTableViewCell
    cell.readings = currentReadings
    cell.updateCell(lineChartData: arrayOfGeneratedChartData[indexPath.row])

    return cell
}

似乎您在单元格中保留了条目,所以不要这样做。将它们保存在tableViewController中。只将所需的数据传递给单元格,不要在单元格方法中执行繁重的任务。

姚星腾
2023-03-14

当有大数据集时,您的图表库可能正在进行一些非常繁重的处理。如果这个库的作者没有考虑到这一点,那么每次滚动并且屏幕上出现一个新单元格时,您都在主线程上执行这个繁重的处理。这肯定会导致口吃。

我希望将单元格设置方法更改为只显示微调器或占位符表,然后开始在后台线程上加载数据和构建图表。这应该会使UtableView的滚动变得平滑,但当您滚动表格时,您会看到带有占位符的单元格,在后台线程处理完成后,图表会在表格中填充。

在Swift的后台线程上运行东西非常简单。

只需确保当您准备好使用图表更新UI时,您可以在主线程上执行(Al UI更新应该在主线程上执行,否则您会看到正在更新的UI中出现奇怪的视觉奇怪或延迟)。因此,在后台线程上完成繁重处理后,也许可以隐藏占位符图像并在主线程上使用动画显示图表。

如果你做了这样的事呢?

func updateCell(chartData: ChartData) {

    DispatchQueue.global(qos: .background).async {
        print("This is run on the background queue")
    self.readings = (readings != nil) ? readings!.readings : []
        self.period = period

        if (chartData.isKind(of: LineChartData.self)) {
            data.lineData = chartData as! LineChartData
        }
        else if (chartData.isKind(of: BarChartData.self)) {
            data.barData = chartData as! BarChartData
        }     

        self.chartView.data = data

        DispatchQueue.main.async {
            // something that triggers redrawing of the chartView.
           chartView.fitScreen()
        }
    }
}

请注意,主线程调用在后台线程执行块中。这意味着所有的东西都将在后台线程上运行,当后台线程的东西完成时,它将调用图表库中的一些东西来执行UI刷新。同样,如果您的图表库被编写为强制在主线程上进行长时间运行的操作,这将没有帮助。

阚砚文
2023-03-14

要获得真正的性能提升,您可能需要实现UITableViewDataSourcePrefting。通过这样做,表视图将调用您的委托,让您提前知道需要一个单元格。这将使您的代码有机会准备和呈现它需要的任何数据。

从留档:

您可以将预取数据源对象与表视图的数据源结合使用,以便在调用tableView(_: cell ForRowAt:)数据源方法之前开始加载单元格的数据。将预取数据源添加到表视图需要以下步骤:

>

  • 创建表视图及其数据源。

    创建一个采用UITableViewDataSourcePrefetching协议的对象,并将其分配给表视图上的prefetchDataSource属性。

    在tableView的实现中,在指定的索引路径处启动单元格所需数据的异步加载(_:prefetchRowsAt:)。

    使用tableView(_:cellForRowAt:)数据源方法中的预取数据准备要显示的单元格。

    当表视图通知您tableView(_:取消PrefetchingForRowsAt:)方法中不再需要数据时,取消挂起的数据加载操作。

  •  类似资料:
    • 我正在使用嵌套的RecycerView。意思是在一个垂直的回收器视图中,我有多个水平的回收器视图 }

    • 我在线性布局中使用滚动视图,问题是布局响应正常,一旦我开始滚动,它就会滞后太多。 我在我的线性布局中使用了这段代码,一旦我触摸了RadiButton或edittext或我向下滚动,它就开始滞后很多。我无法理解这个问题,我使用的图像尺寸小于100kb

    • 我正在做一个音乐播放器。因此,在相册部分,我尝试加载毕加索库的相册图像。图像加载正确,但当我滚动时,就会出现应用滞后问题。我也尝试使用glide,但性能没有改善。我认为此问题是由于此链接的图像加载而出现的。“content://media/external/audio/albumart“。是否有其他方法?如果没有,那么如何提高滚动性能..”

    • 我有一个水平回收视图。每个子级包含一个TextView和一个垂直RecyclerView。垂直RecyclerView的子级仅包含TextView。 垂直滚动非常平滑,但水平滚动滞后很多。我已经尝试在onBindViewHolder中使用swapAdapter,而不是setAdapter,但这并没有解决问题。我也尝试过更改数据集并调用notifyDataSetChanged(),但这也没有帮助。

    • 我有一个当用户滚动时显示隐藏单元格的tableView。不确定为什么会出现这种情况。 在视图中DidLoad() 用户点击按钮后,表格将以可设置动画的方式展开。 在 func tableView(_ tableView: UITableView, cellForRowAt 索引路径: 索引路径) - 当我滚动时,所有单元格都被隐藏。我看到它们是在单元格中创建的,但是,它们不会出现在我的屏幕上。为什