优化消耗大量内存和CPU的javafx代码

时间:2014-08-21 10:20:04

标签: image split grid javafx imageview

下面的代码是为筹款晚餐购买土地,目的是显示购买土地平方米的进度(约2976平方米)。每次购买一平方米时,应用程序都会添加一个与实际1平方米相对应的图像图块。最终,瓷砖(大约2976个)就像一个网格一样填满,以便在完全购买后完成土地。

每块瓷砖的大小约为320字节,总共有2976块瓷砖。

我还在下面展示了一个图片示例。

enter image description here

让我对这段代码感到疯狂的事情(在javafx中)是它消耗了我的1个处理器的大约90%到100%,并且随着tile添加到内存使用量不断增加,直到代码缓冲区耗尽内存并且一段时间后程序崩溃了。这在筹款晚宴上是不可取的。

完整的代码可用于测试 你需要将boolean split更改为true false,这将为你分割图像(大约3000张图像);

https://github.com/rihani/Condel-Park-Fundraiser/tree/master/src/javafxapplication3

使用所有内存和CPU的主要罪魁祸首是下面显示的AnimationTimer()函数,我想知道是否有人可以帮助我减少此代码中的内存和CPU使用率。

简要说明如何使用下面的代码,将土地划分为2个窗格,当第一个grid_pane1填满时,第二个窗格grid_pane2开始填充。 还有一个闪烁的图块用于显示当前的进度。

我正在使用total_donnation ++;测试代码,但通常会使用mysql来提取在发现晚餐期间提出的新值

AnimationTimer()代码:

translate_timer = new AnimationTimer() {
            @Override public void handle(long now) {
                if (now > translate_lastTimerCall + 10000_000_000l) 
                {
                    old_total_donnation = total_donnation;
                    try 
                    {
//                        c = DBConnect.connect();
//                        SQL = "Select * from donations";
//                        rs = c.createStatement().executeQuery(SQL);
//                        while (rs.next()) 
//                        {total_donnation = rs.getInt("total_donnation");}
//                        c.close();

                        total_donnation ++;

                        if(total_donnation != old_total_donnation)
                        {
                            System.out.format("Total Donation: %s \n", total_donnation);

                            old_total_donnation = total_donnation;
                            if (!pane1_full)
                            {
                                grid_pane1.getChildren().clear();
                                grid_pane1.getChildren().removeAll(imageview_tile1,hBox_outter_last);                                
                            }
                            grid_pane2.getChildren().clear();
                            grid_pane2.getChildren().removeAll(imageview_tile2,hBox_outter_last);

                            for(i=0; i<=total_donnation; i++)
                            {
                                if (pane1_full){  System.out.println("Pane 1 has not been redrawn"); break;}
                                file1 = new File("pane1_img"+i+".png");
                                pane1_tiled_image = new Image(file1.toURI().toString(),image_Width,image_Height,false,false);
                                imageview_tile1 = new ImageView(pane1_tiled_image);
                                grid_pane1.add(imageview_tile1, current_column_pane1,current_row_pane1);   
                                current_column_pane1 = current_column_pane1+1;
                                if (current_column_pane1 == max_columns_pane1 )
                                {
                                    current_row_pane1 = current_row_pane1+1;
                                    current_column_pane1 = 0;
                                }
                                if (i == max_donnation_pane1 ){ pane1_full = true; System.out.println("Pane 1 full"); break;}
                                if (i == total_donnation)
                                {
                                    if (i != max_donnation_pane1)
                                    {

                                        hBox_outter_last = new HBox();
                                        hBox_outter_last.setStyle(style_outter);
                                        hBox_outter_last.getChildren().add(blink_image);

                                        ft1 = new FadeTransition(Duration.millis(500), hBox_outter_last);
                                        ft1.setFromValue(1.0);
                                        ft1.setToValue(0.3);
                                        ft1.setCycleCount(Animation.INDEFINITE);
                                        ft1.setAutoReverse(true);
                                        ft1.play();
                                        grid_pane1.add(hBox_outter_last, current_column_pane1,current_row_pane1);
                                    }
                                }
                            }

                            if (i < total_donnation)
                            {
                                total_donnation_left = total_donnation - max_donnation_pane1;
                                for(j=0; j<=total_donnation_left; j++)
                                {
                                    file2 = new File("pane2_img"+j+".png");
                                    pane2_tiled_image = new Image(file2.toURI().toString(),image_Width,image_Height,false,false);
                                    imageview_tile2 = new ImageView(pane2_tiled_image);
                                    grid_pane2.add(imageview_tile2, current_column_pane2,current_row_pane2);       
                                    current_column_pane2 = current_column_pane2+1;
                                    if (current_column_pane2 == max_columns_pane2 )
                                    {
                                        current_row_pane2 = current_row_pane2+1;
                                        current_column_pane2 = 0;
                                    }
                                    if (j == max_donnation_pane2 ){ System.out.println("Pane 2 full"); break;}
                                    if (j == total_donnation_left)
                                    {
                                        if (j != max_donnation_pane2)
                                        {
                                            hBox_outter_last = new HBox();
                                            hBox_outter_last.setStyle(style_outter);
                                            hBox_outter_last.getChildren().add(blink_image);

                                            ft = new FadeTransition(Duration.millis(500), hBox_outter_last);
                                            ft.setFromValue(1.0);
                                            ft.setToValue(0.3);
                                            ft.setCycleCount(Animation.INDEFINITE);
                                            ft.setAutoReverse(true);
                                            ft.play();

                                            grid_pane2.add(hBox_outter_last, current_column_pane2,current_row_pane2);
                                        }
                                    }  
                                }
                            }  
                            current_column_pane1 =0;
                            current_row_pane1=0;
                            current_column_pane2=0;
                            current_row_pane2=0;
                        }
                    }
                    catch (Exception ex) {}
                    translate_lastTimerCall = now;

                }
            }
        };

2 个答案:

答案 0 :(得分:1)

  1. 首先,您创建了许多永不停止的无限期FadeTransitions。这些会随着时间的推移而增加,并导致内存和CPU泄漏。在开始新的转换之前,您应该stop()转换。或者,您只需要一次转换来插入DoubleProperty的值,然后将节点的不透明度绑定到此属性:

    DoubleProperty opacity = new SimpleDoubleProperty();
    Transition opacityTransition = new Transition() {
        protected void interpolate(double frac) {
            opacity.set(frac);
        }
    };
    
    // elsewhere
    hBox_outter_last.opacityProperty().bind(opacity);
    
  2. 您可能需要事先预先加载所有图像切片,以免在循环中从磁盘读取。

  3. 您在每个周期中不必要地破坏并重建场景的大部分内容。您应该修改您的代码,只添加新的图块而不是全部删除它们并从头开始重新创建它们。

  4. 最后,当您实际查询数据库时,您应该从不同的线程而不是JavaFX应用程序线程执行此操作,因为您的UI在查询时将无响应(例如,不动画您的淡入淡出过渡)

答案 1 :(得分:0)

我有一个建议:

  • 请勿使用2个面板拆分图像。一个用于显示整个图像。第二个是与第一个窗格重叠的网格窗格。因此,购买平方米时,相应网格单元的背景将变为透明。