Hi i made one small application to show all sdcard images should display in my application as Thumbnail view .my program is like following
Here problem is that in simulator it loads fast and accurate where as phone it take lots of time. it is loaded some of 30MB around not getting problem. whare it is 80MB around it is not showing images on my screen.
Note: This is perfectly working in simulator but Not device
and my images path is “file:///SDCard/images/”
My code is:
this is my application starter class
public class StartUp extends UiApplication{
public static void main(String[] args) {
StartUp start=new StartUp();
start.enterEventDispatcher();
}
public StartUp() {
pushScreen(new ViewerMainScreen());
}
}
this is my ViewerMainScreen.java
public class ViewerMainScreen extends MainScreen implements FieldChangeListener{
private ObjectListField fileList;
private String currentPath = "file:///";
public VerticalFieldManager vert_manager=null;
private BitmapField before[]=null,next[]=null;
private int size=0;Border b1,b2;
TableLayoutManager colFMgr=null;
private Vector img_data=null;
private int count=0;
public ViewerMainScreen() {
super();
setTitle("Browse to image...");
initGUI();
}
public void initGUI() {
try {
// add(getFileList());
img_data=getAllList("file:///SDCard/images");
b1=BorderFactory.createSimpleBorder(new XYEdges(3,3,3,3),new XYEdges(Color.RED, Color.RED, Color.RED, Color.RED),Border.STYLE_SOLID);
b2=BorderFactory.createSimpleBorder(new XYEdges(0,0,0,0));
size=img_data.size();
before=new BitmapField[size];
next=new BitmapField[size];
vert_manager=new VerticalFieldManager(VERTICAL_SCROLL|VERTICAL_SCROLLBAR){
protected void sublayout(int maxWidth, int maxHeight) {
super.sublayout(Display.getWidth(),Display.getHeight());
setExtent(Display.getWidth(),Display.getHeight());
}
};
colFMgr = new TableLayoutManager(new int[] {
TableLayoutManager.USE_PREFERRED_SIZE,
TableLayoutManager.USE_PREFERRED_SIZE,
TableLayoutManager.USE_PREFERRED_SIZE,
TableLayoutManager.USE_PREFERRED_SIZE,
}, Manager.HORIZONTAL_SCROLL|VERTICAL_SCROLL|VERTICAL_SCROLLBAR);
for(int i= 0;i < size;i++)
{
EncodedImage load_img=EncodedImage.getEncodedImageResource("loading.jpg");
before[i] = new BitmapField(load_img.getBitmap(),Field.FOCUSABLE){
protected boolean navigationClick(int status,int time) {
fieldChangeNotify(0);
return super.navigationClick(status, time);
}
protected void onFocus(int direction)
{
this.setBorder(b1);
invalidate();
}
protected void onUnfocus()
{
this.setBorder(b2);
invalidate();
}
};
colFMgr.add(before[i]);
}
add(colFMgr);
Thread t=new Thread(){
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
callImageThread();
}
};
t.start();
} catch (Exception e) {
Dialog.alert(e.getMessage());
}
}
private void callImageThread() {
for(int i=0;i<size;i++)
{
if(count==6){
try {
Thread.sleep(400);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
ImageThread th=new ImageThread(this, "file:///SDCard/images/"+img_data.elementAt(i), i);
th.start();
count++;
}
}
public void ReplaceImage(EncodedImage img,int index)
{
before[index].setBitmap(img.getBitmap());
before[index].setChangeListener(this);
count--;
System.out.println("Thread count: ========================"+Thread.activeCount()+"============================================="+count);
}
public void fieldChanged(Field field, int context) {
for(int i=0;i<size;i++)
{
if(field==before[i])
{
synchronized (UiApplication.getEventLock()) {
EncodedImage img=null;
img=loadFile("file:///SDCard/images/"+img_data.elementAt(i));
int displayWidth = Fixed32.toFP(Display.getWidth()-100);
int imageWidth = Fixed32.toFP(img.getWidth());
int scalingFactorX = Fixed32.div(imageWidth, displayWidth);
int displayHeight = Fixed32.toFP(Display.getHeight()-100);
int imageHeight = Fixed32.toFP(img.getHeight());
int scalingFactorY = Fixed32.div(imageHeight, displayHeight);
EncodedImage scaledImage = img.scaleImage32(scalingFactorX, scalingFactorY);
UiApplication.getUiApplication().pushScreen(new ZoomScreen(scaledImage));
}
}
}
}
public void displayMessage(final String message)
{
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
Dialog.inform(message);
}
});
}
private Vector getAllList(String path){
Vector data=new Vector();
FileConnection fileConnection=null;
try{
fileConnection = (FileConnection) Connector.open(path);
if (fileConnection.isDirectory()) {
Enumeration directoryEnumerator = fileConnection.list();
while (directoryEnumerator.hasMoreElements()) {
data.addElement(directoryEnumerator.nextElement());
}
}
}catch (Exception e) {
System.out.println(e.getMessage());
}
finally
{
if(fileConnection!=null){
try {
fileConnection.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return data;
}
private EncodedImage loadFile(String path) {
FileConnection fileConnection =null;
InputStream inputStream =null;
EncodedImage encodedImage=null;
try {
fileConnection = (FileConnection) Connector.open(path);
if(fileConnection.exists()){
inputStream = fileConnection.openInputStream();
byte[] imageBytes = new byte[(int)fileConnection.fileSize()];
inputStream.read(imageBytes);
encodedImage = EncodedImage.createEncodedImage(imageBytes, 0, imageBytes.length);
if(fileConnection!=null){
try {
fileConnection.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(inputStream!=null){
try {
inputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
} catch (IOException e) {
Dialog.alert("Insert an SD Card.");
}
return encodedImage;
}
}
This is my ImageThread.java
public class ImageThread extends Thread{
private ViewerMainScreen screen;
private String path;
private int index;
private EncodedImage scaledImage=null;
public ImageThread(ViewerMainScreen screen,String path,int index) {
this.screen=screen;
this.path=path;
this.index=index;
}
public void callMainScreen(EncodedImage eimg,int Rindex) {
screen.ReplaceImage(eimg, Rindex);
}
public void run() {
FileConnection fileConnection =null;
InputStream inputStream =null;
EncodedImage encodedImage=null;
try {
fileConnection = (FileConnection) Connector.open(path);
if(fileConnection.exists()){
inputStream = fileConnection.openInputStream();
byte[] imageBytes = new byte[(int)fileConnection.fileSize()];
inputStream.read(imageBytes);
encodedImage = EncodedImage.createEncodedImage(imageBytes, 0, imageBytes.length);
int displayWidth = Fixed32.toFP(100);
int imageWidth = Fixed32.toFP(encodedImage.getWidth());
int scalingFactorX = Fixed32.div(imageWidth, displayWidth);
int displayHeight = Fixed32.toFP(100);
int imageHeight = Fixed32.toFP(encodedImage.getHeight());
int scalingFactorY = Fixed32.div(imageHeight, displayHeight);
scaledImage = encodedImage.scaleImage32(scalingFactorX, scalingFactorY);
callMainScreen(scaledImage, index);
}
} catch (IOException e) {
Dialog.alert("Insert an SD Card.");
}
finally
{
if(fileConnection!=null){
try {
fileConnection.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(inputStream!=null){
try {
inputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
please help me how to increase performance of my code
I would load images only when user scrolls screen. For example load first two screens on screen start (in different thread) and load next when user is moving down. So set
ScrollListenerto your manager and use field postion and height to determine which is on the screen and which is going to be on screen soon.Also use limited size thread pool and queue for images loading. Unfortunately java concurrent is not par of j2me. But there are several similar pattern implementations, like ThreadPool.
And It would be super if you also remember case when user scrolls fast – cancel scheduled loading if it’s not required. For every loading task remember
BitmapFieldposition and size. Before task starts file loading check ifBitmapFieldis visible (going to be visible) with current scroll position.Also be aware about threads count. I see that you try to sleep main loading thread when count is 6. But there is still small possibility that 400 ms is not enough to finish work for current threads and you can easily start to create more threads.
Also minor things – use Bitmap.scaleInto (If you target is 5.0+), use synchronization around
sizefield,nextis never used, use a little better names likenextImages,threadsCount, etc.