【问题标题】:Suggestions to load data faster更快加载数据的建议
【发布时间】:2013-10-04 16:34:32
【问题描述】:

我正在寻找解决方案,以超过 5 秒(这是我现在正在加载的秒数)从 SQLite 加载 20 个项目。首先,我使用的是自定义 Listview 适配器。

我在 1 秒内加载了 5 个项目。我尝试加载 20 个项目,并在 5 秒内加载它们。 这是我从数据库中检索的字段:int、String、String、int、Bytes、float、int。

如你所想,得到字节后我将它们转换为位图。

Bitmap image = convertBlobToImage(cursor.getBlob(4));
// Using this function:
  public Bitmap convertBlobToImage(byte[] value){
        byte[] new_value = Base64.decode(value, 0);
        return BitmapFactory.decodeByteArray(new_value, 0, new_value.length);   
    }

因此,在我的类字段中,他们将获得不是字节,而是已经获得位图。 阅读时间长的原因之一可能是位图。我刚刚对Paint进行了测试。我保存了两个相同的图像,一个在 BMP 中,另一个在 JPG 中。 JPG 图像大小为 2,87KB,BMP 420KB!!

使用上面的代码,我得到的结果是什么?可能的解决方案之一是:http://www.mkyong.com/java/how-to-convert-byte-to-bufferedimage-in-java/?

你们怎么看?谢谢。


编辑: 我正在搜索,我发现了关于 onDestroy() 的信息。我也没有实现“runOnUiThread”,我就是这样说的。但我认为并没有给我带来更好的结果。你怎么看?这能提高性能吗?

  @Override
    protected void onDestroy() {
        super.onDestroy();
        listView.setAdapter(null);
    }
// And I also tried to put runOnUiThread:
runOnUiThread(new Runnable() {
             @Override
             public void run() {
                 Bundle extras = getIntent().getExtras();
                 if (extras != null) {
                     DatabaseHandler db = new DatabaseHandler(Produtos.this);
                     display_products = db.get_all_oc_product(extras.getString("category_id"));

                     listView = (ListView) findViewById(R.id.product_listview);
                     inputSearch = (EditText) findViewById(R.id.product_inputSearch);

                     adapter = new itemAdapter(Produtos.this,R.layout.row, display_products);
                     listView.setAdapter(adapter);
                 }
             }
         });

编辑 (2):我设法将显示 20 个项目的时间缩短了 3 秒。我通过在查询后关闭与数据库的所有连接来实现这一点。我没有正确地做到这一点。 正确方法:

cursor db.query(...)
try{
 // Code
} finally {
  cursor.close();
  db.close();
}

编辑 (3):除了编辑 (2) 上的解决方案之外,我发现的问题之一是图像问题。 所以,我开始看它们,我看到了 2000x1800 和 300kb 甚至更大的图像,我很快发现问题就在这里。

因此,在 PHP 网络服务中,我开发了一个函数来将图像大小调整为一半并将它们转换为 jpg。

function resize($filePath){
    list($width, $height) = getimagesize($filePath);

    $percent = 0.5;

        $newwidth = $width * $percent;
        $newheight = $height * $percent;

        $thumb = imagecreatetruecolor($newwidth, $newheight);

        $ext = pathinfo($filePath, PATHINFO_EXTENSION);
        $source = null;

        if($ext == "png"){
            $source = imagecreatefrompng($filePath);
        }else if($ext == "jpg" || $ext == "jpeg"){
            $source = imagecreatefromjpeg($filePath);
        }

        // Resize
        imagecopyresized($thumb, $source, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);

        // Output
        $temporary = "C:\\xampp\\htdocs\\MyExample\\images\\temporary\\" . basename($filePath);
        imagejpeg($thumb, $temporary . ".jpg", 50);
        ImageDestroy($thumb);

        return $temporary . ".jpg";

}

使用这个解决方案,我减少了惊人的 1 秒加载 47 个项目的时间!!

【问题讨论】:

  • 你真的需要将它们存储在数据库中吗?
  • 我认为您应该学习如何使用 Traceview 并找出问题所在,而不仅仅是猜测:developer.android.com/tools/debugging/debugging-tracing.html
  • 通常 blob 不存储在数据库中。
  • @SnakeDoc 但它通过 DB API,对吗? (另外,数据库存储为文件,如果我想这样看的话......)
  • 除了在 Android 生命周期中关闭数据库,而不是 Java - 即在 Activity.onStop() 中。 JVM 终止不一定发生在 Android 中

标签: java android image bitmap


【解决方案1】:

我建议检查java.nio.* 软件包之一以加载您的图像。 NIO 是非阻塞的,这意味着您可以异步加载图像,从而每次完成更多的工作。

NIO 还在系统上(在 jvm 之外)使用了本机缓冲区,因此它可以防止 java 不得不将内容读入它的堆,这再次使事情变得更快(本机)。在这里使用NIO 也有很多好处。

【讨论】:

  • 如何使用 nio 将图像从数据库加载到 Bitmap 对象中?
  • 他可能使用某种 InputStream,要使用 NIO,您只需在该流上打开一个通道,然后读入缓冲区,然后将其吐出到一个对象(在这种情况下为图像)。所以他需要修改他的convertBlobToImage() 方法。
  • NIO 是一个可以尝试的解决方案。我也看到了这个解决方案:stackoverflow.com/questions/10081008/… 因为,我可以在虚拟设备中加载 5 个图像,但是如果我尝试(在虚拟设备中)加载 20 个图像,我会收到错误:pastebin.com/LC9Aygzh。但在我的平板电脑中,我可以显示数据。
  • 该错误是因为您的 ADK 虚拟设备已用完虚拟 RAM。您的平板电脑上可能有更多 RAM(比如 1GB 而不是虚拟 android,它可能不像 512MB)。按照你做事的方式,它必须先将所有数据读入内存,然后才能对其进行处理。 NIO 将通过缓冲区将其流式传输,以帮助避免该问题。
  • 我会尽可能地给蔚来一个机会,也许这个周末。我发现错误是因为 RAM,我增加了 RAM,但我仍然有同样的错误。但我将在另一台计算机上使用另一个模拟器进行测试。请参阅我的编辑 (2)。
【解决方案2】:

这个问题的另一面有点难以帮助,但有一些通用提示:

  1. 使用某种形式的分析来确定是哪一部分让你放慢了速度。是否加载实际的光标是一个问题?还是字节转换?除非您进行测量,否则很难说 - 否则您可能会浪费大量时间优化不会减慢您速度的东西。最简单的分析示例:

    long startTime = SystemClock.elapsedRealTime();
    suspectedSlowFunctionCall();
    long endTime = SystemClock.elapsedRealTime();
    Log.d(TAG, "Method duration: " + (endTime - startTime));
    

    正如墨菲先生在 cmets 中提到的,还有一些工具可以帮助您完成这项任务。 android 开发者网站有一个great post 展示了如何使用包含在 SDK 中的 traceview。

  2. 如果可以避免的话,一般的智慧是不要将图像存储在数据库中。如果您存储文件路径并保存文件,则调试和使用(以及系统加载)会容易得多。

  3. Android 的 BitmapFactory 应该能够处理 JPEG。如果您想使用 JPG,请随意

  4. 如果某些东西慢得无法修复,请不要在 UI 线程上执行此操作!使用AsyncTask 之类的东西来执行慢速操作,并在加载时将结果一一显示给用户。这总是比在用户等待困惑时停止的操作更可取。

【讨论】:

  • 嘿。 1) - 我如何使用分析?如何安装到 eclipse 中或启用它? 2) - Webservice 以 BLOB 格式检索图像。您是否建议将它们自动转换为图像并存储到 SD 卡或设备内存中,然后将路径保存到 SQLite db 中? 3) - 是否有可能使用我在帖子中显示的代码将其调整为 JPG??
  • @user2742861 嗯,这很有趣...如果您不知道它们是什么类型的图像,则可能不值得尝试转换它 - 据我们所知,它们可能已经是 JPG .无论如何,我怀疑图像的大小是您的问题 - 但除非您对其进行分析,否则我们永远不会知道
  • 尝试jvisualvm 以准确查看代码中的大减速/挂起的确切位置。它是一个免费的分析器,现在包含在 oracle jdk 中。
  • 大部分图片是JPG,但也有一些PNG。请在下面查看我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-18
  • 2021-12-26
  • 2015-10-29
  • 1970-01-01
  • 2020-03-21
  • 2020-10-18
相关资源
最近更新 更多