Infinite Scroll weird behavior

20 views
Skip to first unread message

Carlos Verdier

unread,
Jun 26, 2017, 12:14:37 PM6/26/17
to CodenameOne Discussions

Hi


I’m making use of the infinite scroll component, and it works well except for one thing. If I use setComponentLimit, I get a weir behavior every time top components are removed. The scroll goes crazy and jumps down. 


I’ve uploaded a video where you can see that effect. The scrolling is smooth at the beginning, but starts to fail a bit later. The video is from actual Android device, not simulator, although I get the same error everywhere.


https://www.youtube.com/watch?v=dxFa7kfnRM4&feature=youtu.be


Here is the relevant parts of the code used.


        Container contPlanes = new Container(new BoxLayout(BoxLayout.Y_AXIS));
        contPlanes.addPullToRefresh(() -> {
            actualizaPlanes(f);
        });
        contPlanes.setScrollableY(true);
        contPlanes.setScrollVisible(false);
        InfiniteScrollAdapter infinito = InfiniteScrollAdapter.createInfiniteScroll(contPlanes, new Runnable() {
            int paginaPlan = 0;
            @Override
            public void run() {            
                ArrayList<Planes> arrayPlanes = fetchDataPlanes(paginaPlan);            
                Container[] contenedorPlan = new Container[arrayPlanes.size()];
                for (int x=0; x<contenedorPlan.length; x++) {
                    Planes plan = arrayPlanes.get(x);
                    if(plan == null) { 
                        InfiniteScrollAdapter.addMoreComponents(contPlanes, new Component[0], false);
                        return;
                    }   
                    SpanLabel tituloPlan = new SpanLabel(plan.getTitulo());
                    tituloPlan.setTextUIID(Display.getInstance().isTablet() ? "ContainerSplash" : "ContainerSplashPhone");

                    Label lblUbicacion = new Label(plan.getLocalidad() + ". " + plan.getDireccion());
                    lblUbicacion.setUIID(Display.getInstance().isTablet() ? "ContainerSplash" : "ContainerSplashPhone");
                    FontImage.setMaterialIcon(lblUbicacion, FontImage.MATERIAL_LOCATION_ON);

                    Container contTitulo = new Container(new BoxLayout(BoxLayout.Y_AXIS));
                    contTitulo.addAll(tituloPlan, lblUbicacion);

                    Button imagenPlan = new Button() {
                        @Override
                        protected Dimension calcPreferredSize() {
                            return new Dimension(anchoImagen, altoImagenFinal);
                        }     
                    };
                    imagenPlan.setUIID("FondoPlan");

                    URLImage imagen = URLImage.createToFileSystem(imgEnc, cachePlanes + plan.getId() + ".png", urlPlanes + plan.getId() + ".png", URLImage.RESIZE_SCALE);                
                    imagenPlan.setIcon(imagen);        
                    final URLImage imagenCopia = imagen;
                    Date fechaPlanGui = plan.getFechaComienzo();
                    String fechaConFormato = traduceFechas(formatoMeta.format(fechaPlanGui));
                    String cadenaFecha;
                    Label lblFecha = new Label(cadenaFecha);
                    lblFecha.setUIID(Display.getInstance().isTablet() ? "ComandoAtras" : "TextoBlancoPhone");
                    FontImage.setMaterialIcon(lblFecha, FontImage.MATERIAL_TODAY);
                    Label lblHora = new Label(horaMeta.format(plan.getFechaComienzo()).equals("00:00") ? "Ver detalles" : horaMeta.format( plan.getFechaComienzo()) + "h");
                    lblHora.setUIID(Display.getInstance().isTablet() ? "ComandoAtras" : "TextoBlancoPhone");
                    FontImage.setMaterialIcon(lblHora, FontImage.MATERIAL_ACCESS_TIME);
                    Label lblPrecio = new Label(plan.getPrecio().equals("0") ? "Gratis" : plan.getPrecio() + "€");
                    lblPrecio.setUIID(Display.getInstance().isTablet() ? "ComandoAtras" : "TextoBlancoPhone");
                    FontImage.setMaterialIcon(lblPrecio, FontImage.MATERIAL_PAYMENT);                                
                    Container contMetadatos = new Container(new GridLayout(3));
                    Button btnFavorita = new Button();
                    if (listaFavoritas.contains(plan.getId() + "_" + formatAntes.format(plan.getFechaComienzo()))) {
                        btnFavorita.setUIID("FondoFavoritaSelec");                    
                        FontImage.setMaterialIcon(btnFavorita, FontImage.MATERIAL_FAVORITE, 6);
                    } else {
                        btnFavorita.setUIID("FondoFavorita");                    
                        FontImage.setMaterialIcon(btnFavorita, FontImage.MATERIAL_FAVORITE_BORDER, 6);
                    }                
                    Container contIconos = new Container(new BoxLayout(BoxLayout.X_AXIS));
                    contIconos.add(btnFavorita);
                    Label lblVeces = new Label("-");
                    lblVeces.setUIID("FondoFavorita");                        
                    contIconos.add(FlowLayout.encloseBottom(lblVeces));                                                                
                    Container contFavorita = new Container(new BorderLayout());
                    contFavorita.add(BorderLayout.EAST, contIconos);
                    contMetadatos.setUIID("TitularSlide");
                    contMetadatos.add(lblFecha).addAll(FlowLayout.encloseCenter(lblHora), FlowLayout.encloseRight(lblPrecio));

                    Container contOverlay = new Container(new BorderLayout());
                    contOverlay.add(BorderLayout.NORTH, contFavorita).add(BorderLayout.SOUTH, contMetadatos);

                    Container contCentro = new Container(new LayeredLayout());
                    contCentro.add(imagenPlan);
                    contCentro.add(contOverlay);
                    contenedorPlan[x] = new Container(new BorderLayout());
                    contenedorPlan[x].setUIID(plan.getDestacado() ? "ComponentePublicidad" : "ComponenteNoticia");
                    contenedorPlan[x].add(BorderLayout.NORTH, contTitulo).add(BorderLayout.CENTER, contCentro);  
                    imagenPlan.addActionListener((evt) -> {
                        f.setTransitionOutAnimator(CommonTransitions.createCover(CommonTransitions.SLIDE_HORIZONTAL, false, 300));
                        detallePlan(f);
                    });
                }
                paginaPlan++;
                InfiniteScrollAdapter.addMoreComponents(contPlanes, contenedorPlan, paginaPlan*6 < planes.length);
            }
        }, true);    
        infinito.setComponentLimit(20);



Shai Almog

unread,
Jun 27, 2017, 1:02:13 AM6/27/17
to CodenameOne Discussions
I don't recall ever using setComponentLimit so it might have been something that was implemented and never tested properly. Looking at the code it seems we remove the components from the top but don't scroll up by the right amount to compensate which might be an issue. I'm not sure if this is fixable without an API change.

Either way you should open an issue on this.

Carlos Verdier

unread,
Jun 27, 2017, 4:29:53 AM6/27/17
to CodenameOne Discussions
Ok, thank you, I've filled an issue.

Out of curiosity, how do you do to avoid out of memory with large amount of components then?

Shai Almog

unread,
Jun 28, 2017, 12:10:00 AM6/28/17
to CodenameOne Discussions
Components take up a very small amount of memory and devices have a relatively large amount of RAM. The main issue is the images displayed in the components which can become an issue if you keep adding components and always creating new images. We try to be very efficient about these.

Scrolling past 5k elements in an infinite scroll takes ages regardless of the technology you use. It feels like more because it all passes in front of you but it's not. So we just never hit those memory limits.
Reply all
Reply to author
Forward
Message has been deleted
0 new messages