超大List频繁GC、造成卡顿,怎么破

雕·不懒惰 2020-12-17 12:16:21
Bresenham画线算法
我把每条线的每个点的x,y坐标存到list<Bean>里面
最后list的size达到几百W,最大会有1000多W
这就导致频繁GC,容易卡死

拿到所有的点对应的坐标后转 RGBA_8888的bitmap
然后显示到ImageView

这是Bresenham画线算法
x0,y0线起点的坐标
x1,y1线终点的坐标

private void getPXpoint(int x0, int y0, int x1, int y1) throws OutOfMemoryError {
if (x0 < 0 || x0 > screen_width * 3)
return;
int x = x0;
int y = y0;

int w = x1 - x0;
int h = y1 - y0;

int dx1 = w < 0 ? -1 : (w > 0 ? 1 : 0);
int dy1 = h < 0 ? -1 : (h > 0 ? 1 : 0);

int dx2 = w < 0 ? -1 : (w > 0 ? 1 : 0);
int dy2 = 0;

int fastStep = Math.abs(w);
int slowStep = Math.abs(h);
if (fastStep <= slowStep) {
fastStep = Math.abs(h);
slowStep = Math.abs(w);

dx2 = 0;
dy2 = h < 0 ? -1 : (h > 0 ? 1 : 0);
}
int numerator = fastStep >> 1;

for (int i = 0; i <= fastStep; i++) {

Point point = new Point(x, y);
points.add(point); //把每个点的x,y坐标存起来
numerator += slowStep;
if (numerator >= fastStep) {
numerator -= fastStep;
x += dx1;
y += dy1;
} else {
x += dx2;
y += dy2;
}
}
}
...全文
4074 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
groovy2007 2020-12-19
  • 打赏
  • 举报
回复
1920*1080*3 = 600W, 这么看来差不过整个屏幕都被画满了,而且一个点上会有很多线段经过,会有很多重复。这种情况下,建议不要用List,也不需要用Point,会创建太多的Point对象。直接用二维数组更好(matrix = new boolean[1920][1080]), matrix[x][y]为true表示下x,y处有点,否则x,y处是空白。代码大致如下:


public class Buf {
	
	final int DeviceWidth;
	final int DeviceHeight;
	boolean[][] matrix;
	
	public Buf(int w, int h)
	{
		this.DeviceWidth = w;
		this.DeviceHeight = h;
		matrix = new boolean[w][h];
	}
	
	public void getPXpoint(int x0, int y0, int x1, int y1) 
	{
		// 确保 x0, y0, x1, y1不超出DeviceWidth, DeviceHeight
		// 不知道原代码为何检测 x0 > screen_width * 3
		
		// Bresenham 画线算法
		// ...
		for (int i = 0; i <= fastStep; i++) {
		       
			//Point point = new Point(x, y); 删除此行
			//points.add(point);  删除此行
			matrix[x][y] = true; //*** 唯一的改动在这里,不用Point, 直接设置相应的坐标 ***
			//....
		}
	}
	
	public void paint1()
	{
		for(int x=0; x<DeviceWidth; x++)
		{
			for(int y=0; y<DeviceHeight; ++)
			{
				if(matrix[x][y]) 
				{
					paint(x,y);// 如果绘图函数支持直接传入x,y
				}
			}
		}
	}
	
	public void paint2()
	{
		Point p = new Point(0,0); //只创建这一个Point
		for(int x=0; x<DeviceWidth; x++)
		{
			for(int y=0; y<DeviceHeight; y++)
			{
				if(matrix[x][y]) 
				{
					p.x = x;
					p.y = y;
					paint(p);// 如果绘图函数只支持Point
				}
			}
		}
	}

	public static void main(String[] args) {
		Buf buf = new Buf(1920, 1080);
		buf.getPXpoint(x0, y0, x1, y1);
		buf.getPXpoint(x1, y1, x2, y2);
		// ....
		buf.paint1(); // Or buf.paint2();
	}

}

引用 16 楼 无fucker说 的回复:
[quote=引用 11 楼 groovy2007 的回复:]是在手机屏幕上画直线吗?多大的屏幕才需要1000W的点呀。最新的苹果6.1英寸的屏幕,分辨率才1170x2532 = 300W个像素,即使把整个屏幕画满也用不了1000W。所以我建议先检查一下代码是不是有bug,为什么会生成这么多的点。
最大4K屏 3840*2160 RGB拆分R、G、B,等于是再*3 需求是这样的 根据当前屏幕分辨率申请一块BUF,比如1920*1080*3(RGB),然后不考虑RGB, 相当于屏幕有(1920*3)*1080那么大,在上面的内存区画斜线,每一根斜线只有一个字节的大小, 颜色值是0或者255(黑白),那这条线根据算法画线就有1080个点 然后就是3条斜线(3个字节)组成一条RGB线,再然后转4字节的ARGB_8888,画满全屏内存区就有1920*3*1080条线 每条线有1080个点,分段操作的话,也是要等好久才[/quote]
雕·不懒惰 2020-12-18
  • 打赏
  • 举报
回复
引用 11 楼 groovy2007 的回复:
是在手机屏幕上画直线吗?多大的屏幕才需要1000W的点呀。最新的苹果6.1英寸的屏幕,分辨率才1170x2532 = 300W个像素,即使把整个屏幕画满也用不了1000W。所以我建议先检查一下代码是不是有bug,为什么会生成这么多的点。
最大4K屏 3840*2160 RGB拆分R、G、B,等于是再*3 需求是这样的 根据当前屏幕分辨率申请一块BUF,比如1920*1080*3(RGB),然后不考虑RGB, 相当于屏幕有(1920*3)*1080那么大,在上面的内存区画斜线,每一根斜线只有一个字节的大小, 颜色值是0或者255(黑白),那这条线根据算法画线就有1080个点 然后就是3条斜线(3个字节)组成一条RGB线,再然后转4字节的ARGB_8888,画满全屏内存区就有1920*3*1080条线 每条线有1080个点,分段操作的话,也是要等好久才
惊喜不断 2020-12-18
  • 打赏
  • 举报
回复
这是什么功能呢? 线的定义:两个点,即使是波浪线也就几个点而已,你这几百万几千万,,有点太夸张了,时时画心跳图一屏的的点也不过千八百,分段显示即可。不明白什么功能
assky124 2020-12-18
  • 打赏
  • 举报
回复
分段绘图,1000W的点绘制出来也没法看啊
老王就是我 2020-12-18
  • 打赏
  • 举报
回复
增加缓存试下
groovy2007 2020-12-18
  • 打赏
  • 举报
回复
是在手机屏幕上画直线吗?多大的屏幕才需要1000W的点呀。最新的苹果6.1英寸的屏幕,分辨率才1170x2532 = 300W个像素,即使把整个屏幕画满也用不了1000W。所以我建议先检查一下代码是不是有bug,为什么会生成这么多的点。
xiaoxiangqing 2020-12-18
  • 打赏
  • 举报
回复
太大了,频繁gc是会这样
比特灵 初级 2020-12-17
  • 打赏
  • 举报
回复
点是不断产生的? 如果是的话,让产生的点存放进队列,另外一个线程取队列并绘图,队列限制大小,生成点大于队列长度时,先进先出抛弃。
不会写代码的猴子 版主 2020-12-17
  • 打赏
  • 举报
回复
一张bitmap的点能装下不?
雕·不懒惰 2020-12-17
  • 打赏
  • 举报
回复
引用 4 楼 不会写代码的猴子 的回复:
你这是取点速度远高于画线速度。。。。可以给list设定最大值,到达最大值时,丢掉一些坐标吧
坐标不能丢的,我 要拿到全部坐标,然后转RGBA_8888的bitmap
追风筝的孩子 2020-12-17
  • 打赏
  • 举报
回复
性能问题一般可以通过减少计算复杂度以及增加缓存来解决。后者的话你可以复用Point,不要每次都new
不会写代码的猴子 版主 2020-12-17
  • 打赏
  • 举报
回复
你这是取点速度远高于画线速度。。。。可以给list设定最大值,到达最大值时,丢掉一些坐标吧
雕·不懒惰 2020-12-17
  • 打赏
  • 举报
回复
引用 1 楼 不会写代码的猴子 的回复:
1.用过的点清除了吗?
清除或者置空都用过了
不会写代码的猴子 版主 2020-12-17
  • 打赏
  • 举报
回复
1.用过的点清除了吗?

80,351

社区成员

发帖
与我相关
我的任务
社区描述
移动平台 Android
androidandroid-studioandroidx 技术论坛(原bbs)
社区管理员
  • Android
  • yechaoa
  • 失落夏天
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧