Android 尝试连续显示图像时OutOfMemoryException

Android 尝试连续显示图像时OutOfMemoryException,android,out-of-memory,Android,Out Of Memory,我试图用屏幕截图显示我从服务器端获得的图像,但在客户端(Android Emulator)上,在通过异常“OutOfMemoryException”运行一段时间后,并没有显示任何图像。所以我需要一些帮助。这是代码 服务器 public class Server { private Connection con; private ScreenCapture sp; private Socket soc; private DataOutputStream out; priva

我试图用屏幕截图显示我从服务器端获得的图像,但在客户端(Android Emulator)上,在通过异常“OutOfMemoryException”运行一段时间后,并没有显示任何图像。所以我需要一些帮助。这是代码

服务器

  public class Server
{
  private Connection con;
  private ScreenCapture sp;
  private Socket soc;
  private DataOutputStream out;
  private DataInputStream in;

public Server() throws IOException, AWTException
{
    con = new Connection();
    sp = new ScreenCapture();  
}

public void init() throws IOException, AWTException

{
    con.setPort(3838);
    ServerSocket serversocket = new ServerSocket(3838);
    soc = serversocket.accept();
    System.out.println("Accepted");
    out = new DataOutputStream(soc.getOutputStream());
    in = new DataInputStream(soc.getInputStream());
    while(true)
    {
    sp.CreateScreenCapture();
    out.write(sp.getScreenCapture());
    }

}

public void closeConnection() throws IOException
{
    soc.close();
}

public static void main(String[] arg)
{

        Server server = null;

    while(true)
    {
        try
        {
            server = new Server();
            server.init();

        }
        catch (IOException ex)
        {
            Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);

        }
        catch (AWTException ex)
        {
            Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
        }
        finally
        {
            try
            {
                server.closeConnection();
            }
            catch (IOException ex)
            {
                Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

    }


}
}

客户

  public class UpdateScreen extends View
{

private DataInputStream input;
private DataOutputStream output;
private Socket soc;
private Bitmap image;



public UpdateScreen(Context context) throws UnknownHostException, IOException 
  {
    super(context);
    // TODO Auto-generated constructor stub
    this.setFocusable(true);
    this.setFocusableInTouchMode(true);
    init();
}

public void init() throws UnknownHostException, IOException
{

    soc = new Socket(InetAddress.getByName("10.0.2.2"), 3838);
    input = new DataInputStream(soc.getInputStream());
    while(true)
    {
    byte[] img = this.getByteArrayFromStream();
    image = BitmapFactory.decodeByteArray(img, 0, img.length);

    }

}


protected void onSizeChanged(int w, int h, int oldw, int oldh) 
   {
    // TODO Auto-generated method stub

     image = Bitmap.createScaledBitmap(image, w, h, false);

    }


public byte[] getByteArrayFromStream() throws IOException
{
    ByteArrayOutputStream buffer = new ByteArrayOutputStream();
    int nread;
    byte[] data = new byte[1042];
    while((nread = input.read(data, 0, data.length)) != -1)
    {
       buffer.write(data, 0, nread);    
    }

     return buffer.toByteArray();
}


@Override
protected void onDraw(Canvas canvas) 
{
    // TODO Auto-generated method stub
    invalidate();
    super.onDraw(canvas);
    canvas.drawBitmap(image, 0, 0, null);

}

}

服务器连续发送图像,客户端在开始绘制之前尝试接收所有数据(无限量)

更好的方法是轮询方法,这意味着客户端请求一个新映像,而服务器提供一个映像


仍然存在一些问题:服务器必须发送图像数据的长度(或在每个图像之后关闭连接),以便客户端知道何时应该停止等待数据并开始处理,并且onDraw()不应该调用invalidate(),因为这可能导致对onDraw()的进一步调用太频繁或太少(如果它可以工作的话).

如果您使用ImageView来显示图像,您可能不需要服务器发送的巨大图像

您可能可以做两件事:

  • 使用像Aquery这样的库,并将其图像加载与视图相关联
  • 自己做这项艰苦的工作-参考Android文档-高效地显示位图

  • 我没有使用图像视图,而是直接在画布上使用。如果服务器在您的控制下,那么您可能可以将其缩小到画布上,如果没有,则可以使用两个其他东西/指针(1)在图像仍处于InputStream级别时缩小图像-参考上面的第2点,(2)ARGB_XXXX的位图非常重,请尽快清除它们(3)如果您不能同时完成这两项工作,并且希望快速完成此工作,请尝试使用webview和照片库插件添加效果,可能会简单得多(4)稍微更改UI模式,例如先向用户显示较小的版本,然后再显示较大的版本(5)如果一切都失败了,你仍然需要它。。。。。尝试探索用于计算的渲染脚本,没有太多文档,它可能会变得棘手(6)我希望您已经将清单设置为使用大型堆