Android:使用 setImageURI 时内存泄漏导致 OOM
我只编写了 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您应该将位图缩小到 ImageView 的大小。例如:
You should downscale the bitmap to the size of your ImageView. For example: