0

我有一个屏幕调用listfield.

public class Main_AllLatestNews extends MainScreen {
private Database_Webservice webservice;
private String[] title, category, date, imagepath = {"no picture", "no picture", "no picture", "no picture","no picture","no picture","no picture","no picture","no picture", "no picture"};
private int[] newsid;
private List_News newslist;

public Main_AllLatestNews(final boolean needdownload) {
    super(USE_ALL_WIDTH);
    webservice = new Database_Webservice();
    add(new Custom_TopField(this, 0, -1, "", 1, 1));
    add(new Custom_BottomField(this, 0));
    add(new Custom_HeaderField(Config_GlobalFunction.latest));
    if (needdownload){
        Main.getUiApplication().pushScreen(
                new Custom_LoadingScreen(30));
        webservice.UpdateAllCatNews();          
    }else {
        webservice.LoadtodayNews(); 
        newsid = new int[webservice.news.size()];
        title = new String[webservice.news.size()];
        category = new String[webservice.news.size()];
        date = new String[webservice.news.size()];
        //imagepath = new String[webservice.news.size()];

        for (int i = 0; i < webservice.news.size(); i++) {
            newslist = (List_News) webservice.news.elementAt(i);
            newsid[i] = newslist.getID();
            title[i] = newslist.getNtitle();
            category[i] = newslist.getNewCatName();
            date[i] = newslist.getNArticalD();
            //imagepath[i] = newslist.getImagePath();
        }
        add(new Custom_ListField(newsid, title, date, category, imagepath, true));
    }
}
}

当我添加时custom_listfield,我得到:

分配定时器 0 失败:没有剩余时隙

这是我的listfield

public Custom_ListField(int newsid[], String title[], String date[],
        String category[], String imagepath[], boolean islatest) {
    super(0, ListField.MULTI_SELECT);
    this.newsid = newsid;
    setCallback(this);
    setBackground(Config_GlobalFunction.loadbackground("background.png"));
    this.islatest = islatest;
    rows = new Vector();

    for (int x = 0; x < title.length; x++) {
        TableRowManager row = new TableRowManager();

        titlelabel = new Custom_LabelField(title[x],
                LabelField.USE_ALL_WIDTH | DrawStyle.LEFT);
        titlelabel.setFont(Font.getDefault().derive(Font.BOLD, 23));
        row.add(titlelabel);

        datelabel = new Custom_LabelField(date[x], DrawStyle.ELLIPSIS
                | LabelField.USE_ALL_WIDTH | DrawStyle.LEFT);
        datelabel.setFont(Font.getDefault().derive(Font.BOLD, 18));
        datelabel.setFontColor(Color.GRAY);
        row.add(datelabel);

        categorylabel = new Custom_LabelField(category[x],
                DrawStyle.ELLIPSIS | LabelField.USE_ALL_WIDTH
                        | DrawStyle.LEFT);
        categorylabel.setFont(Font.getDefault().derive(Font.BOLD, 18));
        categorylabel.setFontColor(Color.RED);
        row.add(categorylabel);

        /*Bitmap imagebitmap = null;
        if (!imagepath[x].toString().equals("no picture")) {
            imagebitmap = Util_ImageLoader.loadImage(imagepath[x]);
        } else {
            imagepath[x] = "image_base.png";
            imagebitmap = Bitmap.getBitmapResource(imagepath[x]);
        }
        image = new BitmapField(imagebitmap, Field.FIELD_HCENTER
                | Field.FIELD_VCENTER);
        row.add(image);*/

        //setRowHeight(image.getBitmapHeight() + 10);
        setRowHeight(70);
        rows.addElement(row);
    }
    setSize(rows.size());
}

在此列表中,它将调用 10 个或更多图像。首先,我将检查发送给它的链接,否则加载本地图像。所以行高必须不相同,但是,它不会为每一行自动设置行高,而是为所有行设置相同的高度。我认为内存不足是因为我调用了太多图像?但我打电话给android也没问题。

这是我的imageloader

public class Util_ImageLoader {

public static Bitmap loadImage(String url) {
    HttpConnection connection = null;
    InputStream inputStream = null;
    EncodedImage bitmap;
    byte[] dataArray = null;

    try {
        // can use this for BlackBerry 5.0+ :
        // connection = (HttpConnection) (new
        // ConnectionFactory()).getConnection(url).getConnection();
        connection = (HttpConnection) Connector
                .open(url + Util_GetInternet.getConnParam(),
                        Connector.READ, true);
        int responseCode = connection.getResponseCode();
        if (responseCode == HttpConnection.HTTP_OK) {
            inputStream = connection.openDataInputStream();
            dataArray = IOUtilities.streamToBytes(inputStream);
        }
    } catch (Exception ex) {
    } finally {
        try {
            inputStream.close();
            connection.close();
        } catch (Exception e) {
        }
    }

    if (dataArray != null) {
        bitmap = EncodedImage.createEncodedImage(dataArray, 0,
                dataArray.length);
        return bitmap.getBitmap();
    } else {
        return null;
    }
}
}

1)我可以做些什么来减少内存的使用?

2)如何设置不同的行高?我已设置bitmap.getbitmapheight(),但不同的位图会有不同的高度。

//更新//

我在模拟器 9930 OS 7.0 和 8520 OS 5.0 上运行。两者的结果也是一样的。Real Device 无法运行,因为在签署密钥后还会提示警告信息try to Secure APi。我完全评论了所有的图像也一样。我既没有打电话也没有打电话给本地图片。我觉得是数据问题?

@AlanLai,你能告诉我们这是在哪个设备上运行,哪个操作系统?它是一个模拟器,还是真正的硬件?您为什么不尝试完全注释掉图像。不显示任何图像(网络图像或本地图像)。看看你是否仍然遇到问题。让我们尝试缩小导致问题的代码的确切位置。注意:请在问题中发布有关您在上面测试的设备的信息,而不是在此处作为评论回复。谢谢

4

3 回答 3

0

如果只有一个TableRowManager设置drawRow值和特定值的布局,怎么样?

于 2012-07-13T07:45:29.107 回答
0

您可以做很多事情来减少内存使用量。一方面,尽量避免将对象在内存中保存的时间超过你真正需要的时间。发生这种情况的一种方法是,如果您在类中保留成员变量,那实际上可能是方法中的局部变量。保留成员变量可能会导致对象的寿命比它们需要的更长,从而阻止释放它们占用的内存。

Util_ImageLoader

例如,在 中Util_ImageLoader,您几乎完成了构造函数中的所有工作。但是,您将结果保存在 (the Bitmap) 附近的静态成员变量 ( _bmap) 中,该变量将其保存在内存中。我知道你这样做是为了打电话getBitmap()。但是,您可以将类更改为:

public class Util_ImageLoader { 

   public static Bitmap loadImage(String url) {       
      HttpConnection connection = null; 
      InputStream inputStream = null; 
      EncodedImage bitmap; 
      byte[] dataArray = null; 

      try { 
         // can use this for BlackBerry 5.0+ :
         // connection = (HttpConnection) (new ConnectionFactory()).getConnection(url).getConnection();
         connection = (HttpConnection) Connector.open(url + Util_GetInternet.getConnParam(),  Connector.READ, 
               true); 
         int responseCode = connection.getResponseCode(); 
         if (responseCode == HttpConnection.HTTP_OK) { 
            inputStream = connection.openDataInputStream();
            dataArray = IOUtilities.streamToBytes(inputStream);            
         } 
      } catch (Exception ex) { 
      } 
      finally { 
         try { 
            inputStream.close(); 
            connection.close(); 
         } catch (Exception e) { 
         } 
      } 

      if (dataArray != null) {
         bitmap = EncodedImage.createEncodedImage(dataArray, 0, dataArray.length);        
         return bitmap.getBitmap(); 
      } else {
         return null;
      }
   } 
} 

因为您的Util_ImageLoader类实际上并没有与之关联的任何状态,所以您可以只使用一种static方法将其变成一个类。静态方法不需要您创建实例Util_ImageLoader来使用它。只需这样做:

Bitmap img = Util_ImageLoader.loadImage("http://domain.com/path/image.png");

这允许加载的图像在 UI 完成后立即释放。现有代码在程序的生命周期内将该图像保存在内存中。

另外,我用有用的方法替换了您使用byte[]缓冲区的自定义代码。IOUtilities.streamtoBytes()让内置库为您完成优化工作。 大多数时候,他们会做得很好。

Util_ImageLoader您的班级中还有一些没有做任何事情的定点缩放代码。它正在创建与原始大小相同的缩放图像。所以,我刚刚删除了该代码。那只能帮助您使用内存。图像处理可能很昂贵。

最后,在创建此方法所需的任何大对象之前,我检查了 Web 服务器返回代码 ( HTTP_OK) 。如果网络请求失败,你当然不想无缘无故浪费内存。

Custom_ListField

同样,您保留了一些对象,可能比需要的时间长。让我们来看看你的成员变量:

private Bitmap bg = Bitmap.getBitmapResource("background.png"),          
    imagebitmap; 

我不知道Custom_ListField你的应用程序中有多少个实例,但是如果你要分配bg给一个常量应用程序资源图像,你至少应该让它成为一个static成员变量,这样如果有 10 个实例Custom_ListField,你只会bg在内存中保留一个变量:

private static Bitmap bg = Bitmap.getBitmapResource("background.png"),          
    imagebitmap;

但是,就您而言,我认为您根本不需要保留该成员变量。您可以简单地在使用它的地方替换它,如下所示:

Background background = BackgroundFactory.createBitmapBackground(Bitmap.getBitmapResource("background.png")); 

然后,该imagebitmap成员也可以替换为局部变量:

 Bitmap imageBitmap = null;
 if (!imagepath[x].toString().equals("no picture")) {            
        imageBitmap = Util_ImageLoader.loadImage(imagepath[x]);            
        imageBitmap = loader.getbitmap();            
 } else {            
        imagepath[x] = "image_base.png";            
        imageBitmap = Bitmap.getBitmapResource(imagepath[x]);            
 }            
 image = new BitmapField(imageBitmap, Field.FIELD_HCENTER | Field.FIELD_VCENTER);        

imageBitmap只需要是局部变量,而不是成员变量。

调试内存使用通常需要拥有整个程序、运行和分析它。仅使用您的一些代码,我看不到使用它的所有其他代码。 每个类创建多少很重要 哪些图像是大的,哪些是小的?这些都是您需要问自己以降低内存使用量的所有问题。

但是,希望我在上面的示例中展示的一般技术可以帮助您入门。

于 2012-07-14T10:28:25.527 回答
0

问题是Custom_ListField. 这应该extends listfield 而不是自定义extends manager

public class Custom_ListField extends ListField {
private String[] title, category, date, imagepath;
private int[] newsid, catsid;
private List_News newslist;
private Bitmap imagebitmap[], localimage = Bitmap
        .getBitmapResource("image_base.png");
private BrowserField webpage;
private Custom_BrowserFieldListener listener;
private boolean islatest;

private Vector content = null;
private ListCallback callback = null;

private int currentPosition = 0;

public Custom_ListField(Vector content, boolean islatest) {
    this.content = content;
    this.islatest = islatest;
    newsid = new int[content.size()];
    title = new String[content.size()];
    category = new String[content.size()];
    date = new String[content.size()];
    imagepath = new String[content.size()];
    catsid = new int[content.size()];
    imagebitmap = new Bitmap[content.size()];

    for (int i = 0; i < content.size(); i++) {
        newslist = (List_News) content.elementAt(i);
        newsid[i] = newslist.getID();
        title[i] = newslist.getNtitle();
        category[i] = newslist.getNewCatName();
        date[i] = newslist.getNArticalD();
        imagepath[i] = newslist.getImagePath();

        if (!imagepath[i].toString().equals("no picture")) {
            imagebitmap[i] = Util_ImageLoader.loadImage(imagepath[i]);
        } else {
            imagebitmap[i] = localimage;
        }
        catsid[i] = newslist.getCatID();
    }

    initCallbackListening();
    this.setRowHeight(localimage.getHeight() + 10);
}

private void initCallbackListening() {
    callback = new ListCallback();
    this.setCallback(callback);
}

private class ListCallback implements ListFieldCallback {

    public ListCallback() {
        setBackground(Config_GlobalFunction
                .loadbackground("background.png"));
    }

    public void drawListRow(ListField listField, Graphics graphics,
            int index, int y, int width) {
        currentPosition = index;
        graphics.drawBitmap(
                Display.getWidth() - imagebitmap[index].getWidth() - 5,
                y + 3, imagebitmap[index].getWidth(),
                imagebitmap[index].getHeight(), imagebitmap[index], 0, 0);
        graphics.setColor(Color.WHITE);
        graphics.drawRect(0, y, width, imagebitmap[index].getHeight() + 10);



        graphics.setColor(Color.BLACK);
        graphics.setFont(Font.getDefault().derive(Font.BOLD, 20));
        graphics.drawText(title[index], 5, y + 3, 0, Display.getWidth()
                - imagebitmap[index].getWidth() - 10);

        System.out.println(Display.getWidth()
                - imagebitmap[index].getWidth() - 10);

        graphics.setColor(Color.GRAY);
        graphics.setFont(Font.getDefault().derive(Font.BOLD, 15));
        graphics.drawText(date[index], 5, y + 6
                + Font.getDefault().getHeight() + 3);

        if (islatest) {
            graphics.setColor(Color.RED);
            graphics.setFont(Font.getDefault().derive(Font.BOLD, 15));
            graphics.drawText(category[index], Font.getDefault()
                    .getAdvance(date[index]) + 3, y + 6
                    + Font.getDefault().getHeight() + 3);
        }
    }

    public Object get(ListField listField, int index) {
        return content.elementAt(index);
    }

    public int getPreferredWidth(ListField listField) {
        return Display.getWidth();
    }

    public int indexOfList(ListField listField, String prefix, int start) {
        return content.indexOf(prefix, start);
    }
}

public int getCurrentPosition() {
    return currentPosition;
}

protected boolean navigationClick(int status, int time) {
    int index = getCurrentPosition();
    if (catsid[index] == 9) {
        if (Config_GlobalFunction.isConnected()) {
            webpage = new BrowserField();
            listener = new Custom_BrowserFieldListener();
            webpage.addListener(listener);

            MainScreen aboutus = new Menu_Aboutus();
            aboutus.add(webpage);
            Main.getUiApplication().pushScreen(aboutus);

            webpage.requestContent("http://www.orientaldaily.com.my/index.php?option=com_k2&view=item&id="
                    + newsid[index] + ":&Itemid=223");
        } else
            Config_GlobalFunction.Message(Config_GlobalFunction.nowifi, 1);
    } else
        Main.getUiApplication().pushScreen(
                new Main_NewsDetail(newsid[index]));
    return true;
}
}
于 2012-07-18T08:53:19.930 回答