0

在我的小部件中,我有一个 imageView,它从用户图库中收集图像,然后将该图像设置为另一个活动的背景。它工作正常,但是当我尝试添加太大的图像文件(例如来自相机的图像)或上传许多图像文件时,我收到“内存不足”错误。看了一会stackoverflow,发现大家都用的基本方法:

public static Bitmap decodeSampleImage(File f, int width, int height) {
try {
    System.gc(); // First of all free some memory

    // Decode image size

    BitmapFactory.Options o = new BitmapFactory.Options();
    o.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(new FileInputStream(f), null, o);

    // The new size we want to scale to

    final int requiredWidth = width;
    final int requiredHeight = height;

    // Find the scale value (as a power of 2)

    int sampleScaleSize = 1;

    while (o.outWidth / sampleScaleSize / 2 >= requiredWidth && o.outHeight / sampleScaleSize / 2 >= requiredHeight)
        sampleScaleSize *= 2;

    // Decode with inSampleSize

    BitmapFactory.Options o2 = new BitmapFactory.Options();
    o2.inSampleSize = sampleScaleSize;

    return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (Exception e) {
    Log.d(TAG, e.getMessage()); // We don't want the application to just throw an exception
}

return null;
}

我还注意到人们也回收了未使用的位图。我理解这是如何工作的,但我不知道我应该把它放在我的编码中的什么地方。

这是我的两个类(Personalize.java,其中收集背景的 imageView 是。它具有 imageView 和两个按钮(一个用于从图库中选择图像,然后将图像显示到 imageView 中,另一个用于设置图像作为背景)。

首先是 Personalize.java:

package com.example.awesomefilebuilderwidget;

IMPORTS

public class Personalize extends Activity implements View.OnClickListener {
Button button;
ImageView image; //the imageview for setting the background
ImageView image2; //the imageview for setting the icon (not focusing on)
Button btnChangeImage;
Button btnChangeImageForIcon;
Button btnSetBackground;
private static final int SELECT_PICTURE = 1;
private static final int SELECT_PICTURE_2 = 2;
private String  selectedImagePath;
Bitmap background;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.personalize);

image = (ImageView) findViewById(R.id.imageView1);
image2 = (ImageView) findViewById(R.id.imageView2Icon);

Button btnChangeImage = (Button) findViewById(R.id.btnChangeImage);    
btnChangeImage.setOnClickListener(this);
Button btnChangeImageForIcon = (Button) findViewById(R.id.btnChangeImageForIcon); 
btnChangeImageForIcon.setOnClickListener(this);
Button btnSetBackground = (Button) findViewById(R.id.btnSetBackground);
btnSetBackground.setOnClickListener(this);

}

@Override 
public void onClick(View v) { 
switch (v.getId()) { 
case R.id.btnChangeImage: 
launchImageChooser(); 
break; 
case R.id.btnChangeImageForIcon: 
launchImageChooser(); 
break; 
case R.id.btnSetBackground: 
setBackgroundImageInDragAndDrop(); 
break; 
} 
} 

private void setBackgroundImageInDragAndDrop() {
Log.d("Personalize", "setBackgroundImageInDragAndDrop() called");
Intent i = getIntent();
//Convert bitmap to byte array to send back to activity
// See: http://stackoverflow.com/questions/11010386/send-bitmap-using-intent-android
ByteArrayOutputStream stream = new ByteArrayOutputStream();
background.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[]byteArray = stream.toByteArray();

i.putExtra("myBackgroundBitmap", byteArray);
setResult(RESULT_OK, i);
finish();
}

private void launchImageChooser() {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(intent, SELECT_PICTURE);
}

public String getPath(Uri uri) {
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
int column_index = cursor
        .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
String imagePath = cursor.getString(column_index);
if(cursor != null) {
cursor.close();
}
return imagePath;
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{

if (resultCode == RESULT_OK) {
if (requestCode == SELECT_PICTURE)
{
    Uri selectedImageUri = data.getData();
    selectedImagePath = getPath(selectedImageUri);
    background = getAndDecodeImage(selectedImagePath);
    if(background != null){
        image.setImageBitmap(background); 
    }           
} else if (requestCode == SELECT_PICTURE_2)
{
    Uri selectedImageUri = data.getData();
    selectedImagePath = getPath(selectedImageUri);
    Bitmap b2 = getAndDecodeImage(selectedImagePath);
    if(b2 != null){
        image2.setImageBitmap(b2);
    }
}    
}
}

private Bitmap getAndDecodeImage(String  selectedImagePath){
try {
    Log.d("Personalize", "selectedImagePath: " + selectedImagePath);
    FileInputStream fileis=new FileInputStream(selectedImagePath);
    BufferedInputStream bufferedstream=new BufferedInputStream(fileis);
    byte[] bMapArray= new byte[bufferedstream.available()];
    bufferedstream.read(bMapArray);
    Bitmap bMap = BitmapFactory.decodeByteArray(bMapArray, 0, bMapArray.length);

    if (fileis != null) 
    {
        fileis.close();
    }
    if (bufferedstream != null) 
    {
        bufferedstream.close();
    }
    return bMap;
} catch (FileNotFoundException e) {                 
    e.printStackTrace();
} catch (IOException e) {                   
    e.printStackTrace();
}   
return null;
}


public boolean saveImageToInternalStorage(Bitmap image) {
   try {
      FileOutputStream fos = this.openFileOutput("desiredFilename.png",     Context.MODE_PRIVATE);
      image.compress(Bitmap.CompressFormat.PNG, 100, fos);
      fos.close();   
      return true;
   } catch (Exception e) {
   return false;
   }
}

}

然后这是我的 Drag_and_Drop_App.java (重要部分的片段——收集位图并设置为背景):

package com.example.awesomefilebuilderwidget;

IMPORTS

public class Drag_and_Drop_App extends Activity {
private static final int SET_BACKGROUND = 10;

private ListView mListAppInfo;
// Search EditText
EditText inputSearch;
public AppInfoAdapter adapter;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // set layout for the main screen
    setContentView(R.layout.drag_and_drop_app);

    // import buttons
    Button btnLinkToFeedback = (Button) findViewById(R.id.btnLinkToFeedback);
    Button btnLinkToPersonalize = (Button) findViewById(R.id.btnLinkToPersonalize);


    // Link to Personalize Screen
    btnLinkToPersonalize.setOnClickListener(new View.OnClickListener() {

        public void onClick(View view) {
            Intent i = new Intent(getApplicationContext(),
                    Personalize.class);
            startActivityForResult(i, SET_BACKGROUND);

        }
    });

}
public Bitmap getThumbnail(String filename) { 
     Bitmap thumbnail = null; 
     try { 
     File filePath = this.getFileStreamPath(filename); 
     FileInputStream fi = new FileInputStream(filePath); 
     thumbnail = BitmapFactory.decodeStream(fi); 
     } catch (Exception ex) { 
     Log.e("getThumbnail() on internal storage", ex.getMessage()); 
     } 
     return thumbnail; 
     } 

     @Override 
     protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
     super.onActivityResult(requestCode, resultCode, data); 
     Log.i("Drag_and_Drop_App", "requestCode: " + requestCode + ", resultCode: " + resultCode); 
     if(requestCode == SET_BACKGROUND && resultCode == RESULT_OK){ 
     byte[] byteArray = data.getByteArrayExtra("myBackgroundBitmap"); 
     Bitmap myBackground = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length); 
     setBackgroundImage(myBackground); 
     } 
     } 

     @SuppressLint("NewApi") 
     private void setBackgroundImage(Bitmap bitmap) { 
     RelativeLayout yourBackgroundView = (RelativeLayout) findViewById(R.id.rl_drag_and_drop_app); 

     Drawable d = new BitmapDrawable(getResources(), bitmap); 

     if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { 
     yourBackgroundView.setBackgroundDrawable(d); 
     } else { 
     yourBackgroundView.setBackground(d); 
     } 
     } 

     }

那么我在哪里可以实现该编码,我还可以在哪里摆脱内存中其他未使用的位图?(回收它们?)

4

0 回答 0