【问题标题】:CustomListView with Bitmap - OutOfMemory Error带位图的 CustomListView - OutOfMemory 错误
【发布时间】:2012-07-23 16:11:36
【问题描述】:

我对 android 开发比较陌生,我正在尝试使用 ImageView 和 TextView 创建自定义 ListView。我正在将 URL 转换为位图图像,然后尝试在 imageView 中显示图像。但是我收到一个错误,我的应用程序立即崩溃。能够在我的 imageView 中显示可绘制对象,我进行了一些修改并尝试显示位图,然后我的应用程序崩溃了。任何帮助将不胜感激。这是我的 3 节课:

编辑 我使用异步任务在单独的线程上获取位图图像,现在我的应用程序不再崩溃。但是当我开始活动时它不显示列表视图。这是我更新的代码。

编辑我再次更改了我的代码,我只在我的异步任务的执行方法中传递了一个 imageView。我现在可以在列表视图中看到文本,但看不到图像。这是我编辑的代码。

编辑 我使用调试器找出位图未显示的原因,我发现我的位图变量为空。这是因为我没有添加互联网权限。添加权限后,我的应用程序开始在给定行崩溃:

 b = BitmapFactory.decodeStream(image_url.openConnection() .getInputStream());

由于 OutofMemory 错误,我收到了 RuntimeException。我不知道如何解决这个问题。我将不胜感激任何帮助。谢谢!

这是我的 Loadimage AsyncTask 类:

 public class LoadImage extends AsyncTask<String, Integer, Bitmap>{

    Context callingContext = null;
    Bitmap b = null;

    ImageView view;

    public LoadImage(ImageView view){

        this.view = view;
    }

    @Override
    protected Bitmap doInBackground(String... arg0) {
        // TODO Auto-generated method stub
        String p_url = "http://java.sogeti.nl/JavaBlog/wp-content/uploads/2009/04/android_icon_256.png";

        Bitmap b = null;
        try {
            URL image_url = new URL(p_url);
            b = BitmapFactory.decodeStream(image_url.openConnection() .getInputStream());

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return b;
    }



    @Override
    protected void onPostExecute(Bitmap result) {
        // TODO Auto-generated method stub
        super.onPostExecute(result);
        view.setImageBitmap(result);

    }   
}

【问题讨论】:

标签: android bitmap android-listview android-arrayadapter out-of-memory


【解决方案1】:

您的代码崩溃了,因为您在严格模式下在 UI 线程上从服务器加载图像文件。这通常被认为是一种不好的做法,因为如果图片需要很长时间才能下载,您的应用似乎已被锁定。

严格模式正在强制崩溃(它抛出异常)。如果您禁用严格模式,它应该可以让您的应用正常工作。但是,在 UI 线程上执行网络 I/O 的问题仍然存在。

更好的长期解决方案是使用AsyncTask 之类的东西。这会将您的图像加载到不同的线程上,从而使您的应用程序保持响应。 AsyncTask 的文档有一个下载图像的简单示例,this helper page 有更多信息。

例如,我可能会将您的代码更改为这样的内容(请注意,我是在没有测试运行的情况下编写此代码的,因此可能存在一些错误):

我会将您的列表条目更改为:

public class CustomList {

    public String iconUrl;
    public String title;
    public CustomList(){
        super();
    }

    public CustomList(String icon, String title) {
        super();
        this.icon = icon;
        this.title = title;
    }
}

然后只将图标 URL 传递给您的列表。

接下来创建一个 AsyncTask:

public class ImageDownloader extends AsyncTask<String, Integer, Bitmap> {
     public ImageDownloader(ImageView view){
          mView = view;
     }

     protected Bitmap doInBackground(String... url) {
        Bitmap b = null;
        try {
            URL image_url = new URL(url);
            b = BitmapFactory.decodeStream(image_url.openConnection() .getInputStream());
            list_data = new CustomList[]{
                    new CustomList(b,"Android")};
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return b;
     }

     protected void onPostExecute(Bitmap result) {
         mView.setImageBitmap(result);
     }
     ImageView mView;
}

然后对于您的适配器,不要设置图像,而是:

new ImageDownloader(holder.thumbnail).execute(cl.icon);

这应该足以让您入门。请注意,此示例存在几个问题:

  1. 可能存在内存泄漏。一般来说你应该 不保留对视图或活动(或其他此类 objects) 像我一样在 AsyncTask 中。
  2. 如果您旋转手机并 列表发生变化,您可能会显示旧的缩略图。
  3. 如果一个 视图被回收,旧的缩略图可能会出现。

【讨论】:

  • 感谢您的帮助!我尝试查看帮助页面,但我不明白如何使用异步任务和自定义数组适配器来加载位图图像。我尝试使用可运行线程,但我的应用程序再次崩溃。我将编辑我的代码。如果您能告诉我哪里出错了,我将不胜感激。
  • 感谢您的示例!但是,我已经在尝试让我的程序与异步任务一起工作。我更新了我的代码并添加了异步任务类。我目前的问题是我的列表视图没有显示出来。
  • 我再次更改了我的代码。我现在正在按照您建议的方式进行操作。但是,尽管我现在确实看到了文本,但我仍然无法在我的列表视图中看到图像。
猜你喜欢
  • 2015-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-14
相关资源
最近更新 更多