从图像 URL 加载图像需要很长时间才能显示

Posted

技术标签:

【中文标题】从图像 URL 加载图像需要很长时间才能显示【英文标题】:Load Image from Image URL taking so much time to display 【发布时间】:2012-10-26 00:58:22 【问题描述】:

我使用了以下链接中的代码:Signare's Blog。我有 10 个图像 URL,想检索它们并将它们显示在我的屏幕上。当我使用上面链接中的代码时,加载所有图像需要 10 多分钟。如何加快加载速度?

URLBitmapField post_img= new URLBitmapField(image_url);
add(post_img);

其中URLBitmapField 类定义为:

import net.rim.device.api.math.Fixed32;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.EncodedImage;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.BitmapField;

public class URLBitmapField extends BitmapField implements URLDataCallback 
    EncodedImage result = null;
    public static EncodedImage _encoded_img = null;
    int _imgWidth = 52;
    int _imgHeight = 62;
    int _imgMargin = 10;

    public URLBitmapField(String url) 
        try 
            http_image_data_extrator.getWebData(url, this);
        
        catch (Exception e) 
    

    public Bitmap getBitmap() 
        if (_encoded_img == null) return null;
        return _encoded_img.getBitmap();
    

    public void callback(final String data) 
        if (data.startsWith("Exception")) return;
        try 
            byte[] dataArray = data.getBytes();
            _encoded_img = EncodedImage.createEncodedImage(dataArray, 0, dataArray.length); // with scale
            _encoded_img = sizeImage(_encoded_img, _imgWidth, _imgHeight);
            setImage(_encoded_img);
            UiApplication.getUiApplication().getActiveScreen().invalidate();
        
        catch (final Exception e)
    

    public EncodedImage sizeImage(EncodedImage image, int width, int height) 
        int currentWidthFixed32 = Fixed32.toFP(image.getWidth());
        int currentHeightFixed32 = Fixed32.toFP(image.getHeight());
        int requiredWidthFixed32 = Fixed32.toFP(width);
        int requiredHeightFixed32 = Fixed32.toFP(height);
        int scaleXFixed32 = Fixed32.div(currentWidthFixed32,requiredWidthFixed32);
        int scaleYFixed32 = Fixed32.div(currentHeightFixed32,requiredHeightFixed32);
        result = image.scaleImage32(scaleXFixed32, scaleYFixed32);
        return result;
    


public interface URLDataCallback 
    public void callback(String data);

http_image_data_extrator定义为:

import java.io.IOException;
import java.io.InputStream;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import net.rim.device.api.system.RadioInfo;
import net.rim.device.api.system.WLANInfo;
import net.rim.device.api.ui.UiApplication;

public class http_image_data_extrator 
    static String url_="";
    static StringBuffer rawResponse=null;

    public static void getWebData(String url, final URLDataCallback callback) throws IOException 
        HttpConnection connection = null;
        InputStream inputStream = null;
        try 
            if ((WLANInfo.getWLANState() == WLANInfo.WLAN_STATE_CONNECTED)&& RadioInfo.areWAFsSupported(RadioInfo.WAF_WLAN)) 
                url += ";interface=wifi";
            
            connection = (HttpConnection) Connector.open(url, Connector.READ, true);
            String location=connection.getHeaderField("location");
            if(location!=null)
                if ((WLANInfo.getWLANState() == WLANInfo.WLAN_STATE_CONNECTED)&& RadioInfo.areWAFsSupported(RadioInfo.WAF_WLAN)) 
                    location += ";interface=wifi";
                
                connection = (HttpConnection) Connector.open(location, Connector.READ, true);
            else
                connection = (HttpConnection) Connector.open(url, Connector.READ, true);
            

            inputStream = connection.openInputStream();
            byte[] responseData = new byte[10000];
            int length = 0;
            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();
            UiApplication.getUiApplication().invokeLater(new Runnable() 
                public void run()
                    callback.callback(result);
                
            );
        
        catch (final Exception ex) 
            UiApplication.getUiApplication().invokeLater(new Runnable() 
                public void run() 
                    callback.callback("Exception (" + ex.getClass() + "): " + ex.getMessage());
                
            );
        
    
  

【问题讨论】:

如果你想在 BlackBerry Screen 上显示 BitMapImages,你可以通过这个Click Here 在那里你会在 BlackBerry RssFeed Reader 上找到一个示例 在您的应用程序中使用数据库将这些图像插入您的数据库中 您能解释一下为什么需要这么大的图像吗?因为没有任何具有这种分辨率的java bb。所以网络很慢,图像很大,下一次调整大小需要一些时间,而且 String.getBytes() 会生成新的数组——更多的内存和时间。没有 wifi 的默认下载类型是 DirectTCP,可能会受到限制 @BlackPearl,如果要下载大文件,需要很长时间。在下载之前你需要在服务器端做一些事情。 您创建一个新字符串只是为了将其内容附加到缓冲区,然后将其丢弃。其中一种优化方法可能是将所有数据读取到 ByteArrayOutputStream 中,然后一次性转换为图像。如果在垃圾收集中浪费了一些时间,这将有所帮助。 【参考方案1】:

在服务器上调整大小

调整服务器上的图像大小是最好的答案。因为下载大图像并缩小它们需要设备上的很多东西(网络、内存、cpu)。

通过代理调整大小

如果图像服务器不在您的控制之下,您仍然可以使用自己的服务器作为调整大小的代理(将图像 url 和所需大小发送到您的服务器,它会获取图像、调整大小并返回调整大小的图像)。也许已经有一项服务可以做到这一点。

更便宜的解码选项

某些解码选项可能会降低解码(和调整大小)的成本。 DECODE_NO_DITHER、DECODE_READONLY 和 DECODE_NATIVE 似乎都值得一试。http://www.blackberry.com/developers/docs/4.2api/net/rim/device/api/system/EncodedImage.html#DECODE_NO_DITHER

串行而不是并行

您提到您正在加载 10 张图片。如果 10 张图像所用时间是 1 张图像所用时间的 10 倍以上,则系统可能会“抖动”。就像它可能会启动所有 10 个请求,然后在回调中同时处理内存中的 10 个全尺寸图像。可以尝试在开始下载下一张之前显示第一张图片,这也让用户可以更快地查看。同样,并行调用 invalidate 10 次(在回调中)可能会导致打嗝。

【讨论】:

以上是关于从图像 URL 加载图像需要很长时间才能显示的主要内容,如果未能解决你的问题,请参考以下文章

从 IPersistMoniker 加载需要很长时间才能加载无法解析的 URL

分享意图需要很长时间才能出现

UIView 需要很长时间才能显示

IconData 需要很长时间才能加载并且不显示图标

在 JSP 中加载图像需要很长时间

iOS中的导航栏按钮图像需要15秒才能加载