android - 应用程序中的内存泄漏(下载、保存和在它们之间循环)

标签 android memory-leaks bitmap android-imageview

我正在构建一个应用程序,它从服务器下载 2 张图像,将它们保存到 SD 卡,然后显示它们(循环,每 15 秒更改一次图像)。

我已完成,但几分钟后程序崩溃:OutOfMemoryError:位图超出 VM 预算的大小。

所以,一定是某处内存泄漏了。我对 Android 编程还很陌生:不太确定我需要做哪些 VM 不会做的清理工作。

有什么帮助吗?

private ImageView mImageView;
private Bitmap mImageBitmap;
public static String rslt="";
/** Called when the activity is first created. */
@SuppressLint("NewApi")
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //Remove title bar
    this.requestWindowFeature(Window.FEATURE_NO_TITLE);

    //Remove notification bar
    this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
    setContentView(R.layout.main);

    mImageView = (ImageView) findViewById(R.id.imageView1);

    mImageBitmap=null;

    final Handler handler = new Handler();
    Runnable runnable = new Runnable() {
        int count = 1;
        public void run() {
            Bitmap bm = getNewImages();
            if (bm != null){
                mImageView.setImageBitmap(bm);
                bm=null;
                System.gc();
                handler.postDelayed(this, 15* 1000);
            }else if(count==1){
                File img1 = new File(Environment.getExternalStorageDirectory(), "1.jpg");
                if(img1.exists()){
                    bm = BitmapFactory.decodeFile(img1.getAbsolutePath());
                    if (bm != null){
                        mImageView.setImageBitmap(bm);
                        bm=null;
                    }
                }

                count = 2;
                System.gc();
                handler.postDelayed(this, 15* 1000);
            }else if (count==2){
                File img2 = new File(Environment.getExternalStorageDirectory(), "2.jpg");
                if(img2.exists()){
                    bm = BitmapFactory.decodeFile(img2.getAbsolutePath());
                    if (bm != null){
                        mImageView.setImageBitmap(bm);

                        bm=null;
                    }
                }

                count=1;
                System.gc();
                handler.postDelayed(this, 15* 1000);
            }

        }
        private Bitmap getNewImages() {
            ConnectivityManager connManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
            NetworkInfo mWifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
            mImageBitmap=null;
            if (mWifi.isConnected()) {
                try{
                    //              EditText ed1=(EditText)findViewById(R.id.editText1);
                    //              String rego=ed1.getText().toString();
                    String rego="AGR905";
                    rslt="START";
                    Caller c=new Caller();
                    c.rego=rego;
                    c.join();
                    c.start();
                    while(rslt=="START")
                    {
                        try
                        {
                            Thread.sleep(10);
                        }
                        catch(Exception ex)
                        {
                        }
                    }
                }
                catch(Exception ex){
                }

                if (rslt.length()<=1600){
                }else{
                    byte[] decodedString = Base64.decode(rslt, Base64.DEFAULT);
                    mImageBitmap = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);

                    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
                    mImageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, bytes);



                    File from = new File(Environment.getExternalStorageDirectory(), "1.jpg");
                    if(from.exists()){
                        File to = new File(Environment.getExternalStorageDirectory(), "2.jpg");
                        from.renameTo(to);
                        from.delete();

                    }
                    //you can create a new file name "test.jpg" in sdcard folder.
                    File f = new File(Environment.getExternalStorageDirectory()+ File.separator + "1.jpg");
                    try {
                        f.createNewFile();

                        //write the bytes in file
                        FileOutputStream fo = new FileOutputStream(f);
                        fo.write(bytes.toByteArray());

                        // remember close de FileOutput
                        fo.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return mImageBitmap;
        }
    };
    handler.postDelayed(runnable, 2000); //for initial delay..

最佳答案

这里有一些东西应该有助于平滑内存。

  1. 完成位图后运行 bitmap.recycle()。
  2. 之后,将它们设置为空。
  3. 每次通过时运行垃圾收集器。 System.gc().
  4. 确保您从 list 中请求大堆。 android:largeHeap="true" 进入应用程序。
  5. 致力于对您的应用程序进行内存分析。参见 this answer有关如何完成此操作的更多详细信息。

关于android - 应用程序中的内存泄漏(下载、保存和在它们之间循环),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14635119/

相关文章:

android - SQLiteDatabase 在查询中需要帮助...请

android - 谷歌分析 Android SDK

android - 平面按钮与凸起按钮

c# - 如何将 Bitmap 对象转换为 Mat 对象(opencv)?

android - 如何在不拉伸(stretch)的情况下调整图像大小?

安卓相机2 : Auto Focus and Exposure

c# - 每次加载新的 JQuery 插件 DataTables 时都会加载更改事件导致内存泄漏

java - 无法使用 LeakCanary 监视 fragment (ClassCastException 错误)

java - Log4j2 自定义 Hibernate Appender 的内存泄漏

python - wxPython -- 如何在某些事件(例如单击)中更新 BitmapButton 的边框样式