Android:使用 setImageURI 时内存泄漏导致 OOM

发布于 2024-12-21 06:28:40 字数 6887 浏览 1 评论 0原文

我只编写了 Java 几天,所以要温柔... :P

我的应用程序使用 SQLite 数据库来保存需要用户提供文本、照片和位置的不同“项目”。问题是,当浏览某些项目时,加载时会发生内存不足异常

myImage.setImageURI(Uri.parse(msavePicture));

第四次或第五次。使用 DDMS 时,您可以看到每次新加载分配的内存都会增加约 0.2Mbyte。我已经搜索了问题并尝试使用

myImage.setImageDrawable(null);

但问题仍然存在。我也尝试将代码更改为

 myBitmap = BitmapFactory.decodeFile(msavePicture);
  ImageView myImage = (ImageView) this.findViewById(R.id.camera_preview);
  myImage.setImageBitmap(myBitmap);   

所以我可以使用 .recycle();但是图片没有加载,它返回null。 msavePicture 是一个如下所示的字符串:

文件:///mnt/sdcard/MyCameraApp/IMG_2011-12-09-01-49.jpg

我已将其包含

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

在清单中,并且我知道图片存在,因为使用 setImageURI 时它可以工作。

所以问题是:我做错了什么导致内存泄漏,如何真正销毁 ImageView,或者为什么 Bitmapfactory 无法解码我的字符串,文件位置是否错误?

为了以防万一,我加入了很多活动。任何与此相关的解决方案或链接将不胜感激!

提前致谢!

(PS:如果有人知道如何将 SQLite 数据库保存到服务器以便您可以用它更新其他手机,我们也将不胜感激!=):DS)

  public class Page3 extends Activity {
private static final int ACTIVITY_CREATE = 0;
public static Long Row = (long) 40;
public static String summarydec = "FAIL";
public static String msavePicture;
public static Location loc;
private EditText mgps_lati;
private EditText mgps_long;
static String gps_long;
static String gps_lati;
private TodoDbAdapter mDbHelper;
public Location myLocation;
public static Bitmap myBitmap;
public Uri uBitmap;


@Override
protected void onCreate(Bundle bundle) {
    super.onCreate(bundle);
    mDbHelper = new TodoDbAdapter(this);
    mDbHelper.open();
    setContentView(R.layout.camera);


        if(msavePicture == null){
        msavePicture = "";
    }
 //     myBitmap = BitmapFactory.decodeFile(msavePicture);
 //     ImageView myImage = (ImageView) this.findViewById(R.id.camera_preview);
 //     myImage.setImageBitmap(myBitmap);       

    ImageView myImage = (ImageView) this.findViewById(R.id.camera_preview);
    myImage.setImageURI(Uri.parse(msavePicture));

    mgps_long = (EditText) findViewById(R.id.gps_long); 
    mgps_lati = (EditText) findViewById(R.id.gps_lati);
    mgps_lati.setText("Latitude:  "+gps_lati);
    mgps_long.setText("Longitude: "+gps_long);
    ////////////////////////////////////////////////////////////
    ///// G P S  -  L Y S S N A R E ////////////////////////////
    ////////////////////////////////////////////////////////////    
    MyLocation myLocation = new MyLocation();
    myLocation.getLocation(this, locationResult);

    Button gps = (Button) findViewById(R.id.gps);
    gps.setOnClickListener(new View.OnClickListener() {
        public void onClick(View view) {

            if (gps_lati != null && gps_long != null) {
                mgps_lati.setText("Latitude:  " +gps_lati);
                mgps_long.setText("Longitude: " +gps_long);
                TodoDetails.save_gps_long = gps_long;
                TodoDetails.save_gps_lati = gps_lati;
                Page1.save_gps_long = gps_long;
                Page1.save_gps_lati= gps_lati;
                Page2.save_gps_long = gps_long;
                Page2.save_gps_lati= gps_lati;
                } else {
                    String Latitude = "Fel vid GPS-hanteringen, arra det!";
                    String Longitude = "Fel vid GPS-hanteringen, arra det!";
                    mgps_lati.setText(Latitude);
                    mgps_long.setText(Longitude);
                }
        }});
    ////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////

    Button camera = (Button) findViewById(R.id.camera);
    camera.setOnClickListener(new View.OnClickListener() {
        public void onClick(View view) {                
            createCamera();
        }});

    Button confirmButton = (Button) findViewById(R.id.todo_edit_button);
    confirmButton.setOnClickListener(new View.OnClickListener() {
        public void onClick(View view) {                
            setResult(RESULT_OK);
            TodoDetails.mPIC = msavePicture;
            Page1.mPIC = msavePicture;
            Page2.mPIC = msavePicture;
            ImageView myImage = (ImageView) findViewById(R.id.camera_preview);
            myImage.setImageDrawable(null);
 //             myBitmap.recycle();
            cancelTimer();
            finish();
        }

    });
}
protected void onPause() {
    super.onPause();
    cancelTimer();
    ImageView myImage = (ImageView) findViewById(R.id.camera_preview);
    myImage.setImageDrawable(null);

}
protected void cancelTimer()
{
    MyLocation myLocation = new MyLocation();
    myLocation.cancelTimer();   
}
protected void onActivityResult(int requestCode, int resultCode,
        Intent intent) {
    super.onActivityResult(requestCode, resultCode, intent);
    cancelTimer();  
    ImageView myImage = (ImageView) findViewById(R.id.camera_preview);
    myImage.setImageURI(Uri.parse(msavePicture));

 //     ImageView myImage = (ImageView) this.findViewById(R.id.camera_preview);
 //     myBitmap = BitmapFactory.decodeFile(msavePicture);
 //     myImage.setImageBitmap(myBitmap);

}
public void onBackPressed (){
    cancelTimer();  
    ImageView myImage = (ImageView) findViewById(R.id.camera_preview);
    myImage.setImageDrawable(null);
 //     Bitmap myBitmap = Page3.myBitmap;
//      myBitmap.recycle();
    finish();
}
////////////////////////////////////////////////////
////////////// A L L A   V Y E R ///////////////////
////////////////////////////////////////////////////
private void createPage1() {
    Intent b = new Intent(this, Page1.class);
    startActivityForResult(b, ACTIVITY_CREATE);
    setResult(RESULT_OK, b);
    finish();
}
private void createPage2() {
    Intent b = new Intent(this, Page2.class);
    startActivityForResult(b, ACTIVITY_CREATE);
    setResult(RESULT_OK, b);
}
private void createTodo() {
    Intent i = new Intent(this, TodoDetails.class);
    startActivityForResult(i, ACTIVITY_CREATE);
    setResult(RESULT_OK, i);
}
private void createCamera() {
    Intent c = new Intent(this, Camera.class);
    startActivityForResult(c, ACTIVITY_CREATE);
    setResult(RESULT_OK, c);
}
//////////////////////////////////////////////////////////
//////// M E N U  T O O L B A R //////////////////////////
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.projektlist, menu);
    return true;
}
public LocationResult locationResult = new LocationResult(){
    @Override
    public void gotLocation(final Location location){
        gps_lati = Double.toString(location.getLatitude());
        gps_long = Double.toString(location.getLongitude());
        }};
 }

i've only programmed java a couple of days so be gentle... :P

My app uses a SQLite database to save different "projects" that needs user provided text, photo and location. The problem is that when browsing through some of the project a Out of Memory-exception occurs when loading the

myImage.setImageURI(Uri.parse(msavePicture));

for the fourth of fifth time. When using DDMS you can see that the allocated memory increases about 0.2Mbyte every new load. I've searched the problem and tried using

myImage.setImageDrawable(null);

but the issue remains. I've also tried changing the code to

  myBitmap = BitmapFactory.decodeFile(msavePicture);
  ImageView myImage = (ImageView) this.findViewById(R.id.camera_preview);
  myImage.setImageBitmap(myBitmap);   

so i could use .recycle(); but the picture doesent load, it returns null.
msavePicture is a string that looks like this:

file:///mnt/sdcard/MyCameraApp/IMG_2011-12-09-01-49.jpg

i've included

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

in manifest and i know the picture exists because when using setImageURI it works.

So the question is: What am i doing wrong to cause the memory leak, how to truly destroy the ImageView, or why can't Bitmapfactory decode my string, is the file location wrong?

I've included alot of the activity just in case. Any solution or links regarding this would be greatly appreciated!

Thanks in advance!

(PS: If someone knows a guide how to save a SQLite database to a server so you can update other phones with it would also be greatly appreciated! =) :DS)

  public class Page3 extends Activity {
private static final int ACTIVITY_CREATE = 0;
public static Long Row = (long) 40;
public static String summarydec = "FAIL";
public static String msavePicture;
public static Location loc;
private EditText mgps_lati;
private EditText mgps_long;
static String gps_long;
static String gps_lati;
private TodoDbAdapter mDbHelper;
public Location myLocation;
public static Bitmap myBitmap;
public Uri uBitmap;


@Override
protected void onCreate(Bundle bundle) {
    super.onCreate(bundle);
    mDbHelper = new TodoDbAdapter(this);
    mDbHelper.open();
    setContentView(R.layout.camera);


        if(msavePicture == null){
        msavePicture = "";
    }
 //     myBitmap = BitmapFactory.decodeFile(msavePicture);
 //     ImageView myImage = (ImageView) this.findViewById(R.id.camera_preview);
 //     myImage.setImageBitmap(myBitmap);       

    ImageView myImage = (ImageView) this.findViewById(R.id.camera_preview);
    myImage.setImageURI(Uri.parse(msavePicture));

    mgps_long = (EditText) findViewById(R.id.gps_long); 
    mgps_lati = (EditText) findViewById(R.id.gps_lati);
    mgps_lati.setText("Latitude:  "+gps_lati);
    mgps_long.setText("Longitude: "+gps_long);
    ////////////////////////////////////////////////////////////
    ///// G P S  -  L Y S S N A R E ////////////////////////////
    ////////////////////////////////////////////////////////////    
    MyLocation myLocation = new MyLocation();
    myLocation.getLocation(this, locationResult);

    Button gps = (Button) findViewById(R.id.gps);
    gps.setOnClickListener(new View.OnClickListener() {
        public void onClick(View view) {

            if (gps_lati != null && gps_long != null) {
                mgps_lati.setText("Latitude:  " +gps_lati);
                mgps_long.setText("Longitude: " +gps_long);
                TodoDetails.save_gps_long = gps_long;
                TodoDetails.save_gps_lati = gps_lati;
                Page1.save_gps_long = gps_long;
                Page1.save_gps_lati= gps_lati;
                Page2.save_gps_long = gps_long;
                Page2.save_gps_lati= gps_lati;
                } else {
                    String Latitude = "Fel vid GPS-hanteringen, arra det!";
                    String Longitude = "Fel vid GPS-hanteringen, arra det!";
                    mgps_lati.setText(Latitude);
                    mgps_long.setText(Longitude);
                }
        }});
    ////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////

    Button camera = (Button) findViewById(R.id.camera);
    camera.setOnClickListener(new View.OnClickListener() {
        public void onClick(View view) {                
            createCamera();
        }});

    Button confirmButton = (Button) findViewById(R.id.todo_edit_button);
    confirmButton.setOnClickListener(new View.OnClickListener() {
        public void onClick(View view) {                
            setResult(RESULT_OK);
            TodoDetails.mPIC = msavePicture;
            Page1.mPIC = msavePicture;
            Page2.mPIC = msavePicture;
            ImageView myImage = (ImageView) findViewById(R.id.camera_preview);
            myImage.setImageDrawable(null);
 //             myBitmap.recycle();
            cancelTimer();
            finish();
        }

    });
}
protected void onPause() {
    super.onPause();
    cancelTimer();
    ImageView myImage = (ImageView) findViewById(R.id.camera_preview);
    myImage.setImageDrawable(null);

}
protected void cancelTimer()
{
    MyLocation myLocation = new MyLocation();
    myLocation.cancelTimer();   
}
protected void onActivityResult(int requestCode, int resultCode,
        Intent intent) {
    super.onActivityResult(requestCode, resultCode, intent);
    cancelTimer();  
    ImageView myImage = (ImageView) findViewById(R.id.camera_preview);
    myImage.setImageURI(Uri.parse(msavePicture));

 //     ImageView myImage = (ImageView) this.findViewById(R.id.camera_preview);
 //     myBitmap = BitmapFactory.decodeFile(msavePicture);
 //     myImage.setImageBitmap(myBitmap);

}
public void onBackPressed (){
    cancelTimer();  
    ImageView myImage = (ImageView) findViewById(R.id.camera_preview);
    myImage.setImageDrawable(null);
 //     Bitmap myBitmap = Page3.myBitmap;
//      myBitmap.recycle();
    finish();
}
////////////////////////////////////////////////////
////////////// A L L A   V Y E R ///////////////////
////////////////////////////////////////////////////
private void createPage1() {
    Intent b = new Intent(this, Page1.class);
    startActivityForResult(b, ACTIVITY_CREATE);
    setResult(RESULT_OK, b);
    finish();
}
private void createPage2() {
    Intent b = new Intent(this, Page2.class);
    startActivityForResult(b, ACTIVITY_CREATE);
    setResult(RESULT_OK, b);
}
private void createTodo() {
    Intent i = new Intent(this, TodoDetails.class);
    startActivityForResult(i, ACTIVITY_CREATE);
    setResult(RESULT_OK, i);
}
private void createCamera() {
    Intent c = new Intent(this, Camera.class);
    startActivityForResult(c, ACTIVITY_CREATE);
    setResult(RESULT_OK, c);
}
//////////////////////////////////////////////////////////
//////// M E N U  T O O L B A R //////////////////////////
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.projektlist, menu);
    return true;
}
public LocationResult locationResult = new LocationResult(){
    @Override
    public void gotLocation(final Location location){
        gps_lati = Double.toString(location.getLatitude());
        gps_long = Double.toString(location.getLongitude());
        }};
 }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

生生漫 2024-12-28 06:28:40

您应该将位图缩小到 ImageView 的大小。例如:

int ratio = widhtOriginal / widthImageView;
// Just an example, you should use more sophisticated algorithm

BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = ratio;

InputStream inputStream = context.getContentResolver().openInputStream(uri);
// Will work for Uri's with "content" scheme,
// otherwise use BitmapFactory.decodeFile(String, Options) and so on

Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, options);

You should downscale the bitmap to the size of your ImageView. For example:

int ratio = widhtOriginal / widthImageView;
// Just an example, you should use more sophisticated algorithm

BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = ratio;

InputStream inputStream = context.getContentResolver().openInputStream(uri);
// Will work for Uri's with "content" scheme,
// otherwise use BitmapFactory.decodeFile(String, Options) and so on

Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, options);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文