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
Regular Contributor
Zenkology
Posts: 92
Registered: ‎01-31-2012
My Device: curve 8520
My Carrier: vodafone

issue in lazy loading

Hi guys, actually um doing an app that needs to make list of managers with a bitmap field and text beside it um using FieldManager to be listed and retrieving bitmaps but when It comes the app stopped till it retreive all bitmaps and that's the source code of the screen and the connection which get the bitmap

 

import java.io.IOException;
import java.io.InputStream;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import net.rim.device.api.math.Fixed32;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.EncodedImage;

public class ImageFromUrl {
	public static Bitmap _bmap;
	HttpConnection connection = null;
	InputStream inputStream = null;
	EncodedImage bitmap;
	byte[] dataArray = null;
	String url;

	ImageFromUrl(String url) {
		this.url = url;

	}

	public byte[] getbitmap() {

		// TODO Auto-generated method stub
		try {
			connection = (HttpConnection) Connector.open(url, Connector.READ,
					true);

			inputStream = connection.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));
			}
			int responseCode = connection.getResponseCode();
			if (responseCode != HttpConnection.HTTP_OK) {
				throw new IOException("HTTP response code: " + responseCode);
			}

			final String result = rawResponse.toString();
			dataArray = result.getBytes();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return dataArray;
	}
}

 and that's the horizontalFieldManager class

 

import net.rim.device.api.i18n.Locale;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.Display;
import net.rim.device.api.ui.Color;
import net.rim.device.api.ui.FieldChangeListener;
import net.rim.device.api.ui.Font;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.TouchEvent;
import net.rim.device.api.ui.TouchGesture;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.BitmapField;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.container.HorizontalFieldManager;
import net.rim.device.api.ui.container.VerticalFieldManager;
import net.rim.device.api.ui.decor.BackgroundFactory;

public class ItemsTitle extends HorizontalFieldManager {
	private ItemBean item;

	// private ActivityIndicatorView indicatorView;
	private BitmapField indicatorView;
	private int fieldHeight;
	private int width;
	private int titleHeight;
	private int dateHeight;
	private int managerWidth;
	private Bitmap bitmap;
	public final static int SMALL_SIZE = 0;
	public final static int LARGE_SIZE = 1;
	public final static int PADDING = 5;

	private ItemsTitle(final ItemBean item, int size) {
		super();
		this.item = item;

		int mySize = 0;
		Font titleFont = null;
		Font dateFont = null;
		if (size == LARGE_SIZE) {
			mySize = getFont().getHeight();
			int allWidth = getFont().getAdvance(item.getLink());
			width = 100;
			titleFont = getFont().derive(Font.PLAIN, mySize);
			int lineNumbers = (allWidth / (Display.getWidth() - width)) + 1;
			titleHeight = (titleFont.getDescent() + titleFont.getHeight()
					* lineNumbers);
			dateFont = getFont().derive(Font.PLAIN, mySize - 3);
			dateHeight = (dateFont.getDescent() + dateFont.getHeight());
			fieldHeight = titleHeight + dateHeight + (PADDING * 2);

		} else if (size == SMALL_SIZE) {
			mySize = getFont().getHeight() - 2;
			width = 80;
			titleFont = getFont().derive(Font.PLAIN, mySize);
			titleHeight = ((titleFont.getDescent() + titleFont.getHeight()) * 2);
			dateFont = getFont().derive(Font.PLAIN, mySize - 3);
			dateHeight = (dateFont.getDescent() + dateFont.getHeight());
			fieldHeight = titleHeight + dateHeight + (PADDING * 2);
		}

		managerWidth = Display.getWidth() - width;
		// width = item.getDescription().getImgWidth();
		VerticalFieldManager fieldManager = new VerticalFieldManager() {
			protected void sublayout(int maxWidth, int maxHeight) {
				super.sublayout(managerWidth, fieldHeight);
				setExtent(managerWidth, fieldHeight);
			}
		};
		fieldManager.setPadding(0, PADDING, 0, PADDING);

		LabelField title = new LabelField(item.getLink(), USE_ALL_WIDTH) {
			protected void layout(int width, int maxHeight) {
				super.layout(managerWidth, titleHeight);
				setExtent(managerWidth, titleHeight);
			}

			protected void paint(Graphics graphics) {
				graphics.setColor(Color.AQUA);
				super.paint(graphics);
			}
		};
		title.setFont(titleFont);
		fieldManager.add(title);

		LabelField date = new LabelField(item.getId(), USE_ALL_WIDTH) {
			protected void layout(int width, int maxHeight) {
				super.layout(managerWidth, dateHeight);
				setExtent(managerWidth, dateHeight);
			}

			protected void paint(Graphics graphics) {
				graphics.setColor(Color.AZURE);
				super.paint(graphics);
			}
		};
		date.setFont(dateFont);
		date.setPadding(PADDING, 0, 0, 0);
		fieldManager.add(date);

		indicatorView = new BitmapField(
				Bitmap.getBitmapResource("loading.png"), BitmapField.HCENTER
						| BitmapField.VCENTER) {
			protected void layout(int width, int height) {
				super.layout(Display.getWidth() - managerWidth, fieldHeight);
				setExtent(Display.getWidth() - managerWidth, fieldHeight);
			}
		};
	
		 imageRecevied();
	
		// indicatorView = LoadingIndicator.getWaitingField(
		// LoadingIndicator.SPINNER_PATTERN, width, height);

		// if (Locale.getDefault().getCode() == Locale.LOCALE_ar) {
		// add(fieldManager);
		// add(indicatorView);
		// } else {
		add(indicatorView);
		add(fieldManager);
		// }

	}

	private void setBitmap(final byte[] bytes) {

		// TODO Auto-generated method stub
		if (bytes != null) {
			if (bytes.length < 500)
				bitmap = Bitmap.getBitmapResource("Placeholder.png");
			else
				bitmap = Bitmap.createBitmapFromBytes(bytes, 0, bytes.length,
						Bitmap.SCALE_TO_FIT);
		}
		if (bitmap != null) {
			Bitmap newBitmap = new Bitmap(width, fieldHeight);
			bitmap.scaleInto(newBitmap, Bitmap.SCALE_TO_FIT);
			indicatorView.setBitmap(newBitmap);
		}
	}

	public boolean isFocusable() {
		return true;
	}

	protected void onFocus(int direction) {
		setVisualState(VISUAL_STATE_FOCUS);
		setBackground(VISUAL_STATE_FOCUS,
				BackgroundFactory.createSolidBackground(Color.CORAL));
		if (direction == 1) {
			if (getTop() + getPreferredHeight() >= (getManager()
					.getVerticalScroll() + getManager().getVisibleHeight()))
				getManager().setVerticalScroll(getTop(), true);
		} else {
			if (getTop() < getManager().getVerticalScroll())
				getManager().setVerticalScroll(getTop(), true);
		}
		super.onFocus(direction);
	}

	protected void onUnfocus() {
		setVisualState(VISUAL_STATE_NORMAL);
		invalidate();
		super.onUnfocus();
	}

	protected void sublayout(int maxWidth, int maxHeight) {
		super.sublayout(Display.getWidth(), fieldHeight);
		setExtent(Display.getWidth(), fieldHeight);
	}

	// protected void paint(Graphics graphics) {
	// if (bitmap == null && !imageRequestSent) {
	// ImageController controller = new ImageController();
	// controller.setImageListener(this);
	// controller.requestImage(item);
	// imageRequestSent = true;
	// }
	// super.paint(graphics);
	// }

	protected boolean navigationClick(int status, int time) {
		fieldChangeNotify(FieldChangeListener.PROGRAMMATIC);
		return true;
	}

	protected boolean touchEvent(TouchEvent message) {
		int x = message.getX(1);
		int y = message.getY(1);
		if (x > 0 && x < getWidth() && y > 0 && y < getHeight()) {
			setFocus();
			if (message.getEvent() == TouchEvent.GESTURE) {
				if (message.getGesture().getEvent() == TouchGesture.TAP) {
					fieldChangeNotify(FieldChangeListener.PROGRAMMATIC);
				}
			}
			return true;
		}
		return super.touchEvent(message);
	}

	public static ItemsTitle getNewInstance(ItemBean item, int size) {
		return new ItemsTitle(item, size);
	}

	public void retry() {
		System.out.println("NewsTitle.retry()");
	}

	public void connectionLost() {
		System.out.println("NewsTitle.connectionLost()");
	}

	public void imageRecevied() {
		// imageRequestSent = false;
		UiApplication.getUiApplication().invokeLater(new Runnable() {

			public void run() {
				// TODO Auto-generated method stub
				ImageFromUrl _img = new ImageFromUrl(item.getThumbLink());
				setBitmap(_img.getbitmap());
			}
		});

	}

 and that's the class responsible of the screen

 

import net.rim.device.api.i18n.Locale;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.ui.DrawStyle;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.BitmapField;
import net.rim.device.api.ui.component.ListField;
import net.rim.device.api.ui.component.ListFieldCallback;
import net.rim.device.api.ui.component.SeparatorField;
import net.rim.device.api.ui.container.MainScreen;

public class ItemsScreen extends MainScreen {
	AppManger appManger;
	ItemBean[] items;
	ListField itemsList;

	int i = 0;

	public ItemsScreen() {
		Locale.setDefault(Locale.get(Locale.LOCALE_ar));
		appManger = AppManger.getInstance();
		items = appManger.getItemsBean();

		for (int i = 0; i < items.length; i++) {

			ItemsTitle newsTitle = ItemsTitle.getNewInstance(items[i],
					ItemsTitle.SMALL_SIZE);
			add(newsTitle);
			add(new SeparatorField());
		}
		
	}

}

 please guys help me

Please use plain text.
Developer
simon_hain
Posts: 15,956
Registered: ‎07-29-2008
My Device: Z10 LE
My Carrier: O2 Germany

Re: issue in lazy loading

use a separate thread for networking.

see
http://supportforums.blackberry.com/t5/Java-Development/What-is-the-Event-Thread/ta-p/446865
----------------------------------------------------------
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
Please use plain text.
Regular Contributor
Zenkology
Posts: 92
Registered: ‎01-31-2012
My Device: curve 8520
My Carrier: vodafone

Re: issue in lazy loading

thank you for your quick response but actually I didn't understand what I should to do
Please use plain text.
Developer
simon_hain
Posts: 15,956
Registered: ‎07-29-2008
My Device: Z10 LE
My Carrier: O2 Germany

Re: issue in lazy loading

use a http://www.blackberry.com/developers/docs/7.1.0api/java/lang/Thread.html for your networking code.
check the httpdemo sample or similar application samples to see possible implementations.

basically you can just surround the code with new Thread(){}.start() (+plus the run method of course).
don't forget to use invokelater if you want to access the UI from the thread.
----------------------------------------------------------
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
Please use plain text.
Regular Contributor
Zenkology
Posts: 92
Registered: ‎01-31-2012
My Device: curve 8520
My Carrier: vodafone

Re: issue in lazy loading

I put the invokeLaterThread surrounding the line of ( imageRecevied():smileywink: in the newsTitle but it didn't affect any thing !
Please use plain text.
Developer
peter_strange
Posts: 19,601
Registered: ‎07-14-2008
My Device: Not Specified

Re: issue in lazy loading

Sounds like you are still not running your bitmap downloads in a separate Thread.  Perhaps you can show us the code to confirm this?

Please use plain text.
Regular Contributor
Zenkology
Posts: 92
Registered: ‎01-31-2012
My Device: curve 8520
My Carrier: vodafone

Re: issue in lazy loading

that's the method which get the images

public byte[] getbitmap() {
		new Thread(new Runnable() {

			public void run() {
				// TODO Auto-generated method stub
				try {
					connection = (HttpConnection) Connector.open(url,
							Connector.READ, true);

					inputStream = connection.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));
					}
					int responseCode = connection.getResponseCode();
					if (responseCode != HttpConnection.HTTP_OK) {
						throw new IOException("HTTP response code: "
								+ responseCode);
					}

					final String result = rawResponse.toString();
					dataArray = result.getBytes();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}
		}).start();
		// TODO Auto-generated method stub

		return dataArray;
	}

 

and I made the method which update the bitmap void to set the indicator

 

private void setBitmap() {

		// TODO Auto-generated method stub

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

			public void run() {
				// TODO Auto-generated method stub
				ImageFromUrl _img = new ImageFromUrl(item.getThumbLink());
				byte[] bytes = _img.getbitmap();
				Bitmap newBitmap = new Bitmap(width, fieldHeight);
				bitmap = Bitmap.createBitmapFromBytes(bytes, 0, bytes.length,
						Bitmap.SCALE_TO_FIT);
				bitmap.scaleInto(newBitmap, Bitmap.SCALE_TO_FIT);

				indicatorView.setBitmap(bitmap);
			}
		});

	}

now it shows nullPointerException and enter the list without updating the images

Please use plain text.
Developer
peter_strange
Posts: 19,601
Registered: ‎07-14-2008
My Device: Not Specified

Re: issue in lazy loading

Unfortunately there are a couple of significant issues with the code:

 

Remember that a Thread does not run synchronously wit the process that invokes it.  Your

getbitmap()

method, assumes that immediately after the

new Thread (...

).start(), that the data is there.  It isn't.  In fact the Thread probably hasn't even started by the time you hit the

return dataArray;

statement.

 

So I have no idea what is going to be in dataArray but I suspect it is not what you want.  Put breakpoints in your code, or System.out.println(..) statements to see this in action.

 

To resolve this you are going to have to figure out a way of only updating the Bitmap on the screen when the response comes back.

 

When it does come back, you should perform as little processing in the invokeLater as possible - i.e. do as much processing using the background Thread as you can.  the only statement that needs to be in the invokeLater is:

indicatorView.setBitmap(bitmap);

All the scaling and so on can be done in the Background Thread.

 

Anyway, to fix this code, you really need to move the code you have in the invokeLater into your getBitmap(), so getBitmap obtains the Bitmap and updates the Ui - with only the Ui update actually being done with invokeLater.

 

Once you have got this going, you may start running into problems with multiple Threads, as I suspect you start a Thread per download and you have quite a number of Bitmaps to get.  Have a think about how you could restrict the number of concurrent downloads you do. 

One final thing.  Don't just do this because we tell you.  Try to understand why this is happening and what you are actually doing about it.  Unless you actually understand these basics, you will hit other problems when you do other processing in Blackberry java (and in other platforms as well actually). 

Please use plain text.