Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Java Development

Reply
Contributor
Balcony
Posts: 17
Registered: ‎08-27-2013
My Device: Blackberry Torch 9860
Accepted Solution

Creating a list of verticalfieldmanager in blackberry is not scrolling well

Hi,

 

I am currently working on a blackberry app that displays news feed with a lot of text and images. I am using verticalfieldmanagers with the contents. It looks cool, but its not scrolling well. Please can someone help with suggestion of making it better. Will a listfield be better? Listfield cannot allow multiline text and multiple images.

 

Please help!!!!

Developer
simon_hain
Posts: 16,282
Registered: ‎07-29-2008
My Device: Z10 LE, Z30, Passport

Re: Creating a list of verticalfieldmanager in blackberry is not scrolling well

welcome to the support forums.

yes, a list field would be better.
i don't know where you got your information about it, listfields can display multiple lines of text and multiple images just fine.
----------------------------------------------------------
feel free to press the like button on the right side to thank the user that helped you.
please mark posts as solved if you found a solution.
@SimonHain on twitter
Contributor
Balcony
Posts: 17
Registered: ‎08-27-2013
My Device: Blackberry Torch 9860

Re: Creating a list of verticalfieldmanager in blackberry is not scrolling well

The issue with listfield is that it is impossible to make other components focusable.
Developer
peter_strange
Posts: 19,610
Registered: ‎07-14-2008
My Device: Not Specified

Re: Creating a list of verticalfieldmanager in blackberry is not scrolling well

Almost all 'feed' applications that I have worked on have used ListField because of the performance benefits.  And you can, if you are prepared to put the work into it, cope with multiple line text fields and multiple images.  What you can't do is have variable size 'rows' and so I have worked on some that used a VFM.  In my experience, scrolling issues with VFMs are usually down to something holding the event Thread, typically during painting but perhaps also while downloading images.  The other issue with VFM's, in fact Managers in general, is that they suffer significantly if you constantly change their layout - for example, adding or removing Fields.

 

The problem of course with issues like this is that it is very difficult to figure out a coding problem without seeing the code, and I suspect you have a lot of it. 

 

Perhaps one option is for you to try to figure out the minimum possible configuration that still causes the problem, then you can paste some sample code that we can review. 

Contributor
Balcony
Posts: 17
Registered: ‎08-27-2013
My Device: Blackberry Torch 9860

Re: Creating a list of verticalfieldmanager in blackberry is not scrolling well

This the code;

 


 

public class ListUi extends HorizontalFieldManager implements
		FocusChangeListener {

	private Classified classified;
	boolean focus = false;
	private BitmapField bf = null;
	private NullField nullField;

	private VerticalFieldManager contents = new VerticalFieldManager(
			Field.USE_ALL_WIDTH);

	public ListUi(Classified classified, long style) {
		super(style);
		this.classified = classified;
		paintUi();
	}

	public void paintUi() {
		this.setPadding(new XYEdges(5, 5, 5, 5));

		nullField = new NullField(Field.FOCUSABLE) {
			public void getFocusRect(XYRect rect) {
				this.getManager().getExtent(rect);
				rect.setLocation(0, 0);
			}
		};

		nullField.setFocusListener(this);

		this.add(nullField);

		bf = new BitmapField(Bitmap.getBitmapResource("cpp.png"),
				Field.FOCUSABLE) {
			boolean focus = false;

			public void onFocus(int direction) {
				focus = true;
				this.setBorder(BorderFactory.createRoundedBorder(new XYEdges(5,
						5, 5, 5), 0x003b5998, Border.STYLE_SOLID));
				super.invalidate();
				super.onFocus(direction);
			}

			public void onUnfocus() {
				focus = false;
				this.setBorder(BorderFactory.createRoundedBorder(new XYEdges(5,
						5, 5, 5), 0x00AAAAAA, Border.STYLE_SOLID));
				super.invalidate();
				super.onUnfocus();
			}

			public boolean navigationClick(int status, int time) {
				return true;
			}
		};
		// bf.setPadding(new XYEdges(5,5,5,5));
		bf.setBorder(BorderFactory.createRoundedBorder(new XYEdges(5, 5, 5, 5),
				0x003b5998, Border.STYLE_SOLID));
		this.add(bf);

		contents.setPadding(new XYEdges(0, 5, 0, 5));
		contents.add(new RichTextField(this.classified.getDescription()));

		HorizontalFieldManager picturePanel = new HorizontalFieldManager(
				Field.USE_ALL_WIDTH | Field.FIELD_HCENTER);

		picturePanel.add(new ImageField("", "pp.png", 64, 64));

		contents.add(picturePanel);

		this.add(contents);

		this.setBorder(BorderFactory.createSimpleBorder(
				new XYEdges(1, 1, 1, 1), new XYEdges(0x00FFFFFF, 0x00FFFFFF,
						0x00999999, 0x00FFFFFF), Border.STYLE_DASHED));

	}

	protected void onFocus(int direction) {
		this.setBackground(BackgroundFactory.createSolidTransparentBackground(
				0x00003366, 20));
		this.setBorder(BorderFactory.createSimpleBorder(
				new XYEdges(1, 1, 1, 1), new XYEdges(0x00FFFFFF, 0x00FFFFFF,
						0x00999999, 0x00FFFFFF), Border.STYLE_SOLID));
		focus = true;
	}

	protected void onUnfocus() {
		this.setBackground(BackgroundFactory.createSolidBackground(0x00FFFFFF));
		this.setBorder(BorderFactory.createSimpleBorder(
				new XYEdges(1, 1, 1, 1), new XYEdges(0x00FFFFFF, 0x00FFFFFF,
						0x00999999, 0x00FFFFFF), Border.STYLE_DASHED));
		focus = false;
	}

	public void focusChanged(Field field, int eventType) {
		if(eventType == FOCUS_GAINED){
			field.setFocus();
		}
		invalidate();
	}
}
Developer
peter_strange
Posts: 19,610
Registered: ‎07-14-2008
My Device: Not Specified

Re: Creating a list of verticalfieldmanager in blackberry is not scrolling well

I think you could save processing by creating Objects once and not doing unecessary things, which would make it a lot faster.  But I will reserve judement until we see code for the ImageField.  Can you paste that please?

 

To make sure we can replicate this processing, some more questions:

1) How many of these do you add?

2) Can we have sample cpp.png and pp.png images (I assume these are just test images - in your real app these would be different for each line?)

3) How long is the text in the RichTextField

4) These will be varying heights depending on the text length - is this what you want?

Contributor
Balcony
Posts: 17
Registered: ‎08-27-2013
My Device: Blackberry Torch 9860

Re: Creating a list of verticalfieldmanager in blackberry is not scrolling well

public class ImageField extends BitmapField {

	private String fileName, url, imageName, remoteUrl;
	private int imageWidth, imageHeight;
	boolean focus = false;

	public String getFileName() {
		return fileName;
	}

	public void setFileName(String fileName) {
		this.fileName = fileName;
	}

	public int getImageWidth() {
		return imageWidth;
	}

	public void setImageWidth(int imageWidth) {
		this.imageWidth = imageWidth;
	}

	public int getImageHeight() {
		return imageHeight;
	}

	public void setImageHeight(int imageHeight) {
		this.imageHeight = imageHeight;
	}

	public ImageField(String externalPath, String noImagePath, int imageWidth,
			int imageHeight, long style) {
		super(Bitmap.getBitmapResource(noImagePath), Field.FOCUSABLE
				| Field.HIGHLIGHT_FOCUS | style);
		this.url = externalPath;
		this.imageWidth = imageWidth;
		this.imageHeight = imageHeight;
		remoteUi();
	}

	public ImageField(String fileName, String noImagePath, int imageWidth,
			int imageHeight) {
		super(Bitmap.getBitmapResource(noImagePath), Field.FOCUSABLE
				| Field.HIGHLIGHT_FOCUS);
		this.fileName = fileName;
		this.imageWidth = imageWidth;
		this.imageHeight = imageHeight;
		paintUi();
	}

	public void onFocus(int direction) {
		focus = true;
		this.setBorder(BorderFactory.createRoundedBorder(
				new XYEdges(5, 5, 5, 5), 0x003b5998, Border.STYLE_SOLID));
		this.setBackground(BackgroundFactory.createSolidBackground(0x003b5998));
		super.onFocus(direction);
		super.invalidate();
	}

	public void onUnfocus() {
		focus = false;
		this.setBorder(BorderFactory.createRoundedBorder(
				new XYEdges(5, 5, 5, 5), 0x00e3e3e3, Border.STYLE_SOLID));
		this.setBackground(BackgroundFactory.createSolidBackground(0x00F3F3F3));
		super.onUnfocus();
		super.invalidate();
	}

	private void remoteUi() {
		final ImageField lui = this;
		UiApplication.getUiApplication().invokeLater(new Runnable() {
			public void run() {
				try {

					URLEncodedPostData dt = new URLEncodedPostData("UTF-8",
							true);
					dt.append("url", url);
					DeviceConnection dm = new DeviceConnection(
							ServerURLs.FETCH_IMAGE, dt.toString(),
							new DeviceConnectionListener() {

								public void onResponse(byte[] response) {
									final Bitmap bt = Bitmap
											.createBitmapFromBytes(response, 0,
													response.length, 1);
									UiApplication.getUiApplication()
											.invokeLater(new Runnable() {
												public void run() {
													if (imageWidth == 0
															&& imageHeight == 0) {
														if (bt.getWidth() > Display
																.getWidth()
																&& bt.getHeight() > Display
																		.getHeight()) {
															lui.setBitmap(ImageField
																	.resizeImage(
																			bt,
																			Display.getWidth(),
																			Display.getHeight()));
														} else {
															lui.setBitmap(bt);
														}
													} else {
														lui.setBitmap(ImageField
																.resizeImage(
																		bt,
																		imageWidth,
																		imageHeight));
													}
												}
											});
								}
							});
					new Thread(dm).start();
				} catch (Exception e) {

				}
			}
		});

	}

	private void paintUi() {
		final ImageField lui = this;
		UiApplication.getUiApplication().invokeLater(new Runnable() {
			public void run() {
				try {
					FileConnection fc = (FileConnection) Connector
							.open(fileName);
					InputStream inputStream = fc.openInputStream();
					byte[] responseData = new byte[10000];
					int length = 0;

					StringBuffer rawResponse = new StringBuffer();
					while (-1 != (length = inputStream.read(responseData))) {
						rawResponse.append(new String(responseData, 0, length));
					}
					byte[] b = rawResponse.toString().getBytes();

					inputStream.close();
					fc.close();

					final Bitmap bt = Bitmap.createBitmapFromBytes(b, 0,
							b.length, 1);
					UiApplication.getUiApplication().invokeLater(
							new Runnable() {
								public void run() {
									if (imageWidth == 0 && imageHeight == 0) {
										lui.setBitmap(bt);
									} else {
										lui.setBitmap(ImageField.resizeImage(
												bt, imageWidth, imageHeight));
									}
								}
							});
				} catch (Exception e) {

				}
			}
		});
	}

	public static Bitmap resizeImage(Bitmap originalImage, int newWidth,
			int newHeight) {
		Bitmap newImage = new Bitmap(newWidth, newHeight);
		originalImage.scaleInto(newImage, Bitmap.FILTER_BILINEAR,
				Bitmap.SCALE_TO_FILL);
		return newImage;
	}

}
Contributor
Balcony
Posts: 17
Registered: ‎08-27-2013
My Device: Blackberry Torch 9860

Re: Creating a list of verticalfieldmanager in blackberry is not scrolling well

All i want is to make it variable, components focusable, and be able to scroll easily.
Developer
peter_strange
Posts: 19,610
Registered: ‎07-14-2008
My Device: Not Specified

Re: Creating a list of verticalfieldmanager in blackberry is not scrolling well

[ Edited ]

There is a significant problem right here:

 

 private void paintUi() {
final ImageField lui = this;
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {

....

  });

 

Run this as a separate Thread.  You are actually doing the file i/o on the Event Thread!

 

I have only looked quickly (in the middle of something else), but I think you just replace this:

UiApplication.getUiApplication().invokeLater(new Runnable() {

with this:

Thread createImage = new Thread(new Runnable() {

and this:

  });

with:

  });

 createImage.start();

 

I note that you are also doing the resizing on the Event Thread - as that is potentially difficult, I think you should do that before your invokeLater.

 

There is one problem with the change I have suggested - it will start a separate Thread for every image, and you will probably run out of Threads.  You might look to do this using a Thread Pool.  Search the forum and elsewhere for ideas about creating a Thread pool. 

Developer
peter_strange
Posts: 19,610
Registered: ‎07-14-2008
My Device: Not Specified

Re: Creating a list of verticalfieldmanager in blackberry is not scrolling well

Apologies, I only looked very briefly.  Looking again I see more.

 

I have just noted that you seem to have assumed that invokelater starts a new Thread, in a number of other places in your code, for example remoteUI().  It doesn't.  It puts a new Runnable to be run on the Event Thread, which is the opposite of what you want.  So I think you need to review all your processing to make sure that you are running everything blocking and compute intensive off the Event Thread. 

 

I'm going to suggest we stop looking at your code until you have done this.  There are other things in your code I don't like, but I suspect this is the most significant factor impacting your performance.