×

Discussion Board

Results 1 to 14 of 14
  1. #1
    Registered User
    Join Date
    Sep 2013
    Posts
    50

    ContainerList problems

    I have an app that is using LWUIT For Series 40. I have a list that needs to have variable cell heights. My understanding is that I need to use ContainerList to achieve this. I'm having a few problems with this.

    Background: Each cell has a BoxLayout (Y-axis) and contains the following:

    - A header container which has a BorderLayout with some stuff in it. It's working perfectly.

    - An image

    - A Text Area

    Here's how I create the ContainerList:

    Code:
    list = new ContainerList(new BoxLayout(BoxLayout.Y_AXIS),new DefaultListModel(data));
    Problems:

    1. Either my TextArea will not grow, or the ContainerList is still trying to force a uniform cell height. I think it's the latter. Here's how I create the TextArea:

    Code:
       TextArea caption = new TextArea();
        caption.getStyle().setBgTransparency(255);
        caption.getStyle().setBgColor(0x060507);
        caption.getStyle().setBorder(null);
        caption.getStyle().setFgColor(0xf0f0f0);
        caption.getStyle().setFont(Font.createSystemFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_MEDIUM));
        caption.getStyle().setMargin(0,10,10,10);
    
        caption.setText(m.caption_text);
        caption.setGrowByContent(true);
        caption.setSingleLineTextArea(false);
        cellCon.addComponent(caption);
    If I just add the Image and the TextArea to the BoxLayout, it appears that the TextArea will not grow; only the first line appears. However, if I put them in a BorderLayout before adding them to the cell layout, with the Image at CENTER and the TextArea at SOUTH, the TextArea does grow, but it appears to grow upward, covering up part of the Image. When this happens, the last line of the TextArea is always right below where the bottom of the Image would be, which is where I want the first line of the TextArea to be. So, like I said, it certainly seems like the ContainerList is still trying to maintaining uniform cell height.


    2. My other problem has to do with how getCellRendererComponent() is called. When using the List class, when the list is created, getCellRendererComponent() is called for about the first 4 or 5 cells. However, with ContainerList, when the list is created, getCellRendererComponent is call for all 80 cells in my list. This is problematic. Why am I getting this different behavior?
    Last edited by james.harpe; 2013-09-24 at 19:31.

  2. #2
    Nokia Developer Champion
    Join Date
    Mar 2013
    Posts
    682

    Re: ContainerList problems

    I would recommend to you to set the ContainerList CellRenderer instead of passing a container in the constrcutor,
    that way you have better control on the look and feel of your cells.

    As for the getCellRendererComponent being called for each cell, its exactly because the list cells can have every height they want so this has to be calculated for each cell.

  3. #3
    Registered User
    Join Date
    Sep 2013
    Posts
    50

    Re: ContainerList problems

    Thanks for your response!

    To your first point: I'm not sure I understand what you mean. My setting of the renderer is actually on the next line, where I just call list.setRenderer(renderer).

    To your second point: Ah, I see. This is problematic for me because each cell has an image, and the cell renderer starts a background thread to download the image for each cell if it is not already cached. So essentially immediately it opens ~80 connections. This is likely what is causing many of my image downloads to fail, where with List they never failed.

    Any idea why the TextArea is not growing with the content? I found a workaround that involves using charWidth/widthOfTextArea, and then manually setting the number of rows. This sort works, but often gets the number of rows incorrect. I don't understand why the TextArea isn't growing by itself.

  4. #4
    Nokia Developer Champion
    Join Date
    Mar 2013
    Posts
    682

    Re: ContainerList problems

    I have a similar ContainerList where i lazy load images on the cell when they are getting called and i dont have many fails or anything like that, you can check out my app Numblr that does this http://store.ovi.com/content/381961

    As for the textarea thing, try init it with rows = 2 and cols = 10 or 20
    there was a bug that if the initial rows number isnt greater than 1 then it wouldnt grow

  5. #5
    Registered User
    Join Date
    Sep 2013
    Posts
    50

    Re: ContainerList problems

    Quote Originally Posted by shai.i View Post
    I have a similar ContainerList where i lazy load images on the cell when they are getting called and i dont have many fails or anything like that, you can check out my app Numblr that does this http://store.ovi.com/content/381961

    As for the textarea thing, try init it with rows = 2 and cols = 10 or 20
    there was a bug that if the initial rows number isnt greater than 1 then it wouldnt grow
    I got the images to load lazily, but these initial getCellRendererComponent() calls are still taking forever. ~10 seconds on a list of ~450 items.

  6. #6
    Nokia Developer Champion
    Join Date
    Mar 2013
    Posts
    682

    Re: ContainerList problems

    can you paste the code you have in the getCellRendererComponent implementation? maybe your doing something there that isnt optimized....

  7. #7
    Registered User
    Join Date
    Sep 2013
    Posts
    50

    Re: ContainerList problems

    Here is the renderer. As you can see, there's some kind of sloppy code in there that prevents it from starting the image download if it's not the case that the cell is about to become visible. Even with this, initial rendering upon list creation is extremely slow.

    Code:
    public Component getCellRendererComponent(Component comp, Object model,
    			Object value, int index, boolean isSelected) {
    		Log.d("Starting getCellRendererComponent for index " + index);
    
            // if its a String.. just display that instead
            if(value instanceof String) {
                Container loading = new Container();
                Label l = new Label((String)value);
                loading.addComponent(l);
                return loading;
            }
    
    		MyModelObject m = (MyModelObject) value;
    		Container cellCon = new Container();
    		cellCon.setLayout(new BoxLayout(BoxLayout.Y_AXIS));
    		cellCon.getStyle().setMargin(Component.TOP, 10);
    		cellCon.getStyle().setMargin(Component.LEFT, 0);
    		Container northCon = new Container();
    		northCon.setLayout(new BorderLayout());
    		northCon.getStyle().setMargin(Component.RIGHT, 10);
    		northCon.getStyle().setMargin(Component.LEFT, 0);
    
    		// Profile image
    		Button profileImageLabel;
    		Image profileImage = (Image) f.getProfileImageCache().get(m.userId);
    		if (profileImage == null || profileImage.getHeight() < 1) {
    
    			int size = 40;
    			String file = "/holder.png";
    			Image i = null;
    			try {
    				i = Image.createImage(file).scaled(size, size);
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    			profileImageLabel = new Button(i);
    
    			Boolean inProgress = (Boolean) profileImageInProgress.get(m.userId);
    			if (inProgress == null)
    				inProgress = new Boolean(false);
    
    			/*
    			 * Because ContainerList calls this method for every cell twice when
    			 * the list is created, we need to only start the image download if
    			 * runCount > 2, or if this is the first cell.
    			 */
    			Integer runCount = (Integer) indexRunCount.get(new Integer(index));
    			if (runCount == null)
    				runCount = new Integer(0);
    
    			if (!inProgress.booleanValue() && m.profile_picture != null
    					&& (runCount.intValue() > 2 || index == 0)) {
    				profileImageInProgress.put(m.userId, new Boolean(true));
    
    				ImageDownloadService ids = new ImageDownloadService(
    						m.profile_picture, new ProfileImageResponseListener(m));
    				
    				ids.addResponseCodeListener(new ActionListener(){
    
    					public void actionPerformed(ActionEvent arg0) {
    						
    						
    					}
    					
    				});
    
    				NetworkManager.getInstance().addToQueue(ids);
    			}
    		} else {
    			profileImageLabel = new Button(profileImage);
    		}
            profileImageLabel.setName(m.userId);
            profileImageLabel.setHeight(40);
            profileImageLabel.setWidth(40);
            profileImageLabel.setPreferredH(40);
            profileImageLabel.setPreferredW(40);
            profileImageLabel.setFocusable(true);
            profileImageLabel.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent actionEvent) {
                    Log.v("Clicked on user icon for: " );
                }
            });
    		//profileImageLabel.getStyle().setMargin(Component.LEFT, 0);
            profileImageLabel.getStyle().setMargin(0,0,10,0);
            profileImageLabel.getStyle().setPadding(0, 0, 0, 0);
            profileImageLabel.setHandlesInput(true);
    		northCon.addComponent(BorderLayout.WEST, profileImageLabel);
    
    		// User name
    		Label userNameLabel = new Label();
    		userNameLabel.setText(m.username);
    		userNameLabel.getStyle().setFgColor(0x50c0bc);
    
    		userNameLabel.getStyle().setFont(
    				Font.createSystemFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN,
    						Font.SIZE_LARGE));
    		northCon.addComponent(BorderLayout.CENTER, userNameLabel);
    
    		// Time Label
    		Label timeLabel = new Label();
    		timeLabel.getStyle().setFont(
    				Font.createSystemFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN,
    						Font.SIZE_MEDIUM));
    		timeLabel.getStyle().setFgColor(0xa5a1b2);
    		timeLabel.setText(TimeSince(m.created_time));
    		northCon.addComponent(BorderLayout.EAST, timeLabel);
    
    		cellCon.addComponent(northCon);
    
    		// Post image
    		Label postImageLabel;
    		Image postImage = (Image) f.getPostImageCache().get(m.mediaId);
    		if (postImage == null || postImage.getHeight() < 1) {
    			int size = 220;
    			String file = "/holder.png";
    			Image i = null;
    			try {
    				i = Image.createImage(file).scaled(size, size);
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    			postImageLabel = new Label(i);
    
    			Boolean inProgress = (Boolean) postImageInProgress.get(m.mediaId);
    			if (inProgress == null)
    				inProgress = new Boolean(false);
    
    			/*
    			 * Because ContainerList calls this method for every cell twice when
    			 * the list is created, we need to start the image download only if
    			 * runCount > 2, or if this is the first cell.
    			 */
    			Integer runCount = (Integer) indexRunCount.get(new Integer(index));
    			if (runCount == null)
    				runCount = new Integer(0);
    
    			if (!inProgress.booleanValue() && m.low_resolution_url != null
    					&& (runCount.intValue() > 2 || index == 0)) {
    
    				postImageInProgress.put(m.mediaId, new Boolean(true));
    
    				Log.d("Starting to get Image for index " + index);
    				ImageDownloadService ids = new ImageDownloadService(
    						m.low_resolution_url, new PostImageResponseListener(m));
    				
    				ids.addResponseCodeListener(new ActionListener(){
    
    					public void actionPerformed(ActionEvent arg0) {
    						
    						
    					}
    					
    				});
    
    				NetworkManager.getInstance().addToQueue(ids);
    			}
    		} else {
    
    			postImageLabel = new Label(postImage);
    		}
    		postImageLabel.getStyle().setMargin(Component.LEFT, 0);
    		postImageLabel.getStyle().setMargin(Component.TOP, 10);
    		postImageLabel.getStyle().setMargin(Component.BOTTOM, 0);
    		cellCon.addComponent(postImageLabel);
    
    		if (m.caption_text != null && m.caption_text.length() > 0) {
    			TextArea caption = new TextArea();
    			int width = 220;
    			caption.getStyle().setBgTransparency(255);
    			caption.getStyle().setBgColor(0x060507);
    
    			caption.getStyle().setBorder(null);
    			caption.getStyle().setFgColor(0xf0f0f0);
    			caption.getStyle().setFont(
    					Font.createSystemFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN,
    							Font.SIZE_MEDIUM));
    			caption.getStyle().setMargin(0, 10, 10, 10);
    			int padding = 10;
    
    			caption.getStyle().setPadding(padding, padding, padding, padding);
    			caption.setGrowByContent(true);
    			caption.setSingleLineTextArea(false);
    			caption.setText(m.caption_text);
    			
    			//setGrowByContent doesn't work, so we have to calculate this manually
    			int numRows = Util.getNumRowsForString(m.caption_text, width
    					- (padding * 2), caption.getStyle().getFont());
    			caption.setRows(numRows);
    			cellCon.addComponent(caption);
    		}
    
    		Container southCon = new Container();
    		southCon.setLayout(new BoxLayout(BoxLayout.X_AXIS));
    		southCon.getStyle().setMargin(Component.LEFT, 10);
    		southCon.getStyle().setMargin(Component.TOP, 0);
    		southCon.getStyle().setMargin(Component.BOTTOM, 0);
    		southCon.getStyle().setPadding(0, 0, 0, 0);
    		Label likeImageLabel = new Label();
    		String file = "/like_temp.png";
    
    		Image i = null;
    		try {
    			i = Image.createImage(file);
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    
    		likeImageLabel.setIcon(i);
    		likeImageLabel.getStyle().setMargin(Component.LEFT, 0);
    		likeImageLabel.getStyle().setMargin(Component.RIGHT, 5);
    		likeImageLabel.getStyle().setMargin(Component.TOP, 0);
    		likeImageLabel.getStyle().setPadding(0, 0, 0, 0);
    
    		southCon.addComponent(likeImageLabel);
    
    		Label numLikes = new Label();
    		numLikes.setText(m.likes);
    		numLikes.getStyle().setFont(
    				Font.createSystemFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN,
    						Font.SIZE_MEDIUM));
    		numLikes.getStyle().setFgColor(0xa5a1b2);
    		numLikes.getStyle().setMargin(Component.LEFT, 0);
    		numLikes.getStyle().setMargin(Component.RIGHT, 15);
    		numLikes.getStyle().setPadding(0, 0, 0, 0);
    		southCon.addComponent(numLikes);
    
    		Label commentImageLabel = new Label();
    		file = "/comment_temp.png";
    
    		i = null;
    		try {
    			i = Image.createImage(file);
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    
    		commentImageLabel.setIcon(i);
    		commentImageLabel.getStyle().setMargin(Component.RIGHT, 10);
    		commentImageLabel.getStyle().setPadding(0, 0, 0, 0);
    		southCon.addComponent(commentImageLabel);
    
    		Label numComments = new Label();
    		numComments.setText(m.numComments);
    		numComments.getStyle().setMargin(Component.LEFT, 0);
    		numComments.getStyle().setPadding(0, 0, 0, 0);
    		numComments.getStyle().setFont(
    				Font.createSystemFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN,
    						Font.SIZE_MEDIUM));
    		numComments.getStyle().setFgColor(0xa5a1b2);
    		southCon.addComponent(numComments);
    
    		cellCon.addComponent(southCon);
    
    		Label d1 = new Label();
    		d1.getStyle().setBgTransparency(255);
    		d1.getStyle().setBgColor(0x0b0b0d);
    		d1.getStyle().setMargin(5, 0, 0, 0);
    		d1.getStyle().setPadding(0, 0, 0, 0);
    		d1.setPreferredW(238);
    		d1.setPreferredH(1);
    
    		Label d2 = new Label();
    		d2.getStyle().setBgTransparency(255);
    		d2.getStyle().setBgColor(0x302d36);
    		d2.getStyle().setMargin(0, 5, 0, 0);
    		d2.getStyle().setPadding(0, 0, 0, 0);
    		d2.setPreferredW(238);
    		d2.setPreferredH(1);
    
    		cellCon.addComponent(d1);
    		cellCon.addComponent(d2);
    
    		Integer runCount = (Integer) indexRunCount.get(new Integer(index));
    		if (runCount == null) {
    			runCount = new Integer(0);
    		}
    		runCount = new Integer(runCount.intValue() + 1);
    
    		indexRunCount.put(new Integer(index), runCount);
    
    		return cellCon;
    	}

  8. #8
    Nokia Developer Champion
    Join Date
    Mar 2013
    Posts
    682

    Re: ContainerList problems

    That is one LONG code to be placed in the getCellRendererComponent method.....
    i havent gone over it with a fine tooth comb BUT from what i see your are both creating your renderer components and layouting them in this method and that is wrong!
    You should pre-create your components, containers and placing them in the correct layouts etc in the constructor of your class so that process will only happen once and then in the getCellRendererComponent only setting their correct values and returning the proper container (so you should keep a reference to all of your components and containers you need to set values for)

    If you do that it will solve your speed issue.

  9. #9
    Nokia Developer Moderator
    Join Date
    Feb 2006
    Location
    Oslo, Norway
    Posts
    28,684

    Re: ContainerList problems

    As you mentioned hundreds of elements, this approach may result in creating hundreds of the placeholder ("/holder.png"). While it may happen that the actual Image implementation internally recognizes the situation and creates the image object only once, it may be safer to do that yourself, so createImage the placeholder once into some member variable (even static), and re-use it whenever you need.

  10. #10
    Registered User
    Join Date
    Sep 2013
    Posts
    50

    Re: ContainerList problems

    Quote Originally Posted by shai.i View Post
    That is one LONG code to be placed in the getCellRendererComponent method.....
    i havent gone over it with a fine tooth comb BUT from what i see your are both creating your renderer components and layouting them in this method and that is wrong!
    You should pre-create your components, containers and placing them in the correct layouts etc in the constructor of your class so that process will only happen once and then in the getCellRendererComponent only setting their correct values and returning the proper container (so you should keep a reference to all of your components and containers you need to set values for)

    If you do that it will solve your speed issue.
    Thanks so much! I will give this a shot.

  11. #11
    Registered User
    Join Date
    Sep 2013
    Posts
    50

    Re: ContainerList problems

    This definitely speeds things up, but seems to mess up my layout. I see some big gaps between cells, some cells are cut off at the bottom. A cell with a messed up layout seems to correct itself once it is clicked. Bear in mind that the whole reason I'm using ContainerList is because I need to accommodate cells of different heights.

  12. #12
    Registered User
    Join Date
    Sep 2013
    Posts
    50

    Re: ContainerList problems

    I think the key is that layout corrects itself when the cell is clicked. Why would that happen? How can I make that happen to begin with?

    EDIT: So I found that if I call revalidate() on cellCon, I don't get the layout problems, but i get the slowness again.

    What I've done now is use the same logic that I'm using to prevent premature image downloads to only call revalidate() if the cell is actually about to become visible. This seems to work pretty well, but it's still not exactly fast. I'm still open to other suggestions on speeding this up.
    Last edited by james.harpe; 2013-10-08 at 14:30.

  13. #13
    Nokia Developer Champion
    Join Date
    Mar 2013
    Posts
    682

    Re: ContainerList problems

    maybe you should repost your current complete code of that class so we'll know better where you stand to help you improve it.

  14. #14
    Registered User
    Join Date
    Sep 2013
    Posts
    50

    Re: ContainerList problems

    Quote Originally Posted by shai.i View Post
    maybe you should repost your current complete code of that class so we'll know better where you stand to help you improve it.
    On second thought...I would say the current speed is fast enough. I would consider this question answered.

Similar Threads

  1. Problems with E51
    By mindlifter in forum Series 40 & S60 Platform Feedback Archive
    Replies: 5
    Last Post: 2010-03-02, 04:44
  2. Problems with JSR-180
    By nils.h in forum Mobile Java Networking & Messaging & Security
    Replies: 0
    Last Post: 2009-01-08, 09:49
  3. Problems about S60 SDK 2.0
    By ouseka in forum Symbian Tools & SDKs
    Replies: 2
    Last Post: 2003-10-30, 11:28
  4. JNI problems!
    By javafnorf in forum Mobile Java Tools & SDKs
    Replies: 1
    Last Post: 2002-10-08, 06:02

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
×