当此警告像无限

时间:2016-07-27 09:23:47

标签: android bitmap garbage-collection

Ivam面对这个记忆问题,它让我发疯。 我的应用程序正在从raspberry接收二进制数据。使用此数据我创建一个int数组,颜色比使用它创建我的位图和显示图像。传输协议是UDP。 当我收到一张图片时没问题,但是当我要求我的覆盆子发送10张图片时,会出现此消息GC_FOR_ALLOC,有时传输会停止而不会发送所有图像。 我用google搜索了这个问题,我添加了Runtime.getRuntime()。gc();的System.gc();我的代码和同样的问题。 我声明我的所有对象都不在循环中以避免每次创建一个新变量,创建我的位图我使用createBitmap(int [] colors,int width,int height,Bitmap.Config config),我在互联网上读到它做这个方法并不好,而是使用createScaledBitmap(Bitmap src,int dstWidth,int dstHeight,boolean filter)。 问题我不知道如何使用createScaledBitmap方法使用我的数组颜色。 另外,我在循环结束时尝试了bitmap.recycle,它发送第一张图像然后我有一个错误,"尝试使用再循环的"。 请有人帮助我。 如果你愿意,我可以添加我的代码。 谢谢 这是代码:

class UDPServer  {
        MainActivity act;

        final String capitalizedSentence = "well received!";
        final byte[] sendData = capitalizedSentence.getBytes();

        public UDPServer(MainActivity act) {
            this.act=act;
        }


        public void connect() throws Exception {
            final  ImageView image = (ImageView) act.findViewById(R.id.imageDisplay);
            final byte[] receiveData1=new byte[40960], receiveData2=new byte[40960], receiveData3=new byte[40960], receiveData4=new byte[40960];
            final DatagramSocket serverSocket=new DatagramSocket(8080);
            final DatagramPacket receivePacket1 = new DatagramPacket(receiveData1, receiveData1.length);
            final DatagramPacket receivePacket2 = new DatagramPacket(receiveData2, receiveData2.length);
            final DatagramPacket receivePacket3 = new DatagramPacket(receiveData3, receiveData3.length);
            final DatagramPacket receivePacket4 = new DatagramPacket(receiveData4, receiveData4.length);

            final Thread udpserver = new Thread()
            {
                    public void run () {



                        try {
                           while (!isInterrupted()) {


                                System.out.println("waiting for the conx");


                                serverSocket.receive(receivePacket1);
                                serverSocket.receive(receivePacket2);
                                serverSocket.receive(receivePacket3);
                                serverSocket.receive(receivePacket4);

                                System.out.println("thank you sir");



                                final Bitmap bitmap=Bitmap.createBitmap(act.afficheImage(
                                        receivePacket1.getData(),
                                        receivePacket2.getData(),
                                        receivePacket3.getData(),
                                        receivePacket4.getData()),
                                        320, 256, Bitmap.Config.ARGB_8888);


                                act.runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        // TODO Auto-generated method stub

                                        image.setImageBitmap(bitmap);
                                    }
                                });
                                InetAddress IPAddress = receivePacket1.getAddress();
                                int port = receivePacket1.getPort();
                                System.out.println("From: " + IPAddress + ":" + port);
                                DatagramPacket sendPacket1 = new DatagramPacket(sendData, sendData.length, IPAddress, port);
                                serverSocket.send(sendPacket1);

                                Runtime.getRuntime().gc();
                                System.gc();
                            }
                            serverSocket.close();
                        } catch (SocketException ex) {
                            System.out.println("UDP Port 8080 is occupied.");
                        } catch (IOException ex1) {
                            System.out.println("Error: " + ex1.getMessage());
                            ex1.printStackTrace();
                        }
                    }
            };
        udpserver.start();
        }
    }

这是afficheImage的方法:

    private static final int WIDTH = 320;
    private static final int HEIGHT = 256;
    public static int a=255<<24;
    public static ByteBuffer buffer1;
    public static short[] array=new short[WIDTH * HEIGHT];
    public static byte[] si=new byte[2];
    public static int[] colors = new int[WIDTH * HEIGHT];
    public static int[] afficheImage(byte[] s1, byte[] s2, byte[] s3, byte[] s4){
        try{
            for (int i=0;i<HEIGHT*WIDTH/4;i++){
                si[0] = s1[2*i];
                si[1] = s1[2*i+1];
                buffer1 = ByteBuffer.wrap(si);
                buffer1.order(ByteOrder.LITTLE_ENDIAN);
                array[i]=buffer1.getShort();
            }

            for (int i=0;i<HEIGHT*WIDTH/4;i++){
                si[0] = s2[2*i];
                si[1] = s2[2*i+1];
                buffer1 = ByteBuffer.wrap(si);
                buffer1.order(ByteOrder.LITTLE_ENDIAN);
                array[i+s1.length/2]=buffer1.getShort();
            }

            for (int i=0;i<HEIGHT*WIDTH/4;i++){
                si[0] = s3[2*i];
                si[1] = s3[2*i+1];
                buffer1 = ByteBuffer.wrap(si);
                buffer1.order(ByteOrder.LITTLE_ENDIAN);
                array[i+s1.length]=buffer1.getShort();
            }

            for (int i=0;i<HEIGHT*WIDTH/4;i++){
                si[0] = s4[2*i];
                si[1] = s4[2*i+1];
                buffer1 = ByteBuffer.wrap(si);
                buffer1.order(ByteOrder.LITTLE_ENDIAN);
                array[i+3*s1.length/2]=buffer1.getShort();
            }


            int delta=foundMax(array)-foundMin(array);
            int min=foundMin(array);

            int r;

            for (int i=0;i<HEIGHT*WIDTH;i++) {
                r = (array[i] - min) * 255/delta;
                colors[i] = a | (r << 16) | (r << 8) | r;
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return colors;
    }

1 个答案:

答案 0 :(得分:0)

编辑:好的,这是真正的答案:

您需要使用OpenGL。

OpenGL会更快,可能会让你的应用看起来像一个视频,这就是你想要的。

对于您的用例来说,最好的事情是OpenGL在后台线程中呈现,因此您可以从网络数据构建像素缓冲区并将其全部呈现在同一个线程中。

代码实际上是为每个“框架”创建一个新的Bitmap,所以你也应该分配一个静态位图。

在您分配connect的{​​{1}}方法的开头,您也应该分配DatagramPacket

Bitmap

然后在获得所有数据后在循环内:

    final Bitmap bitmap = Bitmap.createBitmap(320, 256, Bitmap.Config.ARGB_8888);

您可能还需要在将缓冲区数据推入其中的服务器线程与尝试将其呈现到 int[] pixels = act.afficheImage( receivePacket1.getData(), receivePacket2.getData(), receivePacket3.getData(), receivePacket4.getData()); bitmap.setPixels(pixels, 0, 320, 0, 0, 320, 256); 的UI线程之间的位图上进行一些同步。

有什么方法可以限制来自Raspberry的数据?您的Android设备可能会在尝试处理网络数据并同时显示图像时不堪重负。

我还可以看到一堆其他的优化来消除大多数临时工作缓冲区,但是当涉及到摆脱OOM异常时,这些并不会真正发挥作用。