2013-01-05 232 views
1

我設計了一個自定義圖像視圖畫廊,就像我的三星Galaxy S3上的魅力,但當我嘗試使它在我的HTC Wildfire S上工作時,它會拋出java.lang。 OutOfMemoryError:位圖大小超過虛擬機預算。代碼如下,任何線索?如何解決位圖大小超過虛擬機預算

public class ImageViewFlipper extends Activity { 

private static final int EXIT = 0; 
private static final int SWIPE_MIN_DISTANCE = 120; 
private static final int SWIPE_MAX_OFF_PATH = 250; 
private static final int SWIPE_THRESHOLD_VELOCITY = 200; 
private static final String DIRECTORY = "/sdcard/edu"; 
private static final String DATA_DIRECTORY = "/sdcard/edu"; 
private static final String DATA_FILE = "/sdcard/imagelist.dat"; 
private GestureDetector gestureDetector; 
View.OnTouchListener gestureListener; 
private Animation slideLeftIn; 
private Animation slideLeftOut; 
private Animation slideRightIn; 
private Animation slideRightOut; 
private ViewFlipper viewFlipper; 
private int currentView = 0; 
List<String> ImageList; 
private int currentIndex = 0; 
private int maxIndex = 0; 

FileOutputStream output = null; 
OutputStreamWriter writer = null; 

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

    requestWindowFeature(Window.FEATURE_NO_TITLE); 
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
      WindowManager.LayoutParams.FLAG_FULLSCREEN); 

    setContentView(R.layout.main); 
    ImageView iv = (ImageView) findViewById(R.id.zero); 

    File data_directory = new File(DATA_DIRECTORY); 
    if (!data_directory.exists()) { 
     if (data_directory.mkdir()) { 
      FileUtils savedata = new FileUtils(); 
      Toast toast = Toast.makeText(ImageViewFlipper.this, 
        "Please wait while we search your SD Card for images...", Toast.LENGTH_SHORT); 
      toast.show(); 
      SystemClock.sleep(100); 
      ImageList = FindFiles(); 
      savedata.saveArray(DATA_FILE, ImageList); 

     } else { 
      ImageList = FindFiles(); 
     } 

    } 
    else { 
     File data_file= new File(DATA_FILE); 
     if (!data_file.exists()) { 
      FileUtils savedata = new FileUtils(); 


      SystemClock.sleep(100); 
      ImageList = FindFiles(); 
      savedata.saveArray(DATA_FILE, ImageList); 
     } else { 
      FileUtils readdata = new FileUtils(); 
      ImageList = readdata.loadArray(DATA_FILE); 
     } 
    } 

    if (ImageList == null) { 
     quit(); 
    } 

    SharedPreferences indexPrefs = getSharedPreferences("currentIndex", 
      MODE_PRIVATE); 
    if (indexPrefs.contains("currentIndex")) { 
     currentIndex = indexPrefs.getInt("currentIndex", 0); 
    } 

    maxIndex = ImageList.size() - 1; 

    Log.v("currentIndex", "Index: "+currentIndex); 

    viewFlipper = (ViewFlipper) findViewById(R.id.flipper); 

    slideLeftIn = AnimationUtils.loadAnimation(this, R.anim.slide_left_in); 
    slideLeftOut = AnimationUtils 
      .loadAnimation(this, R.anim.slide_left_out); 
    slideRightIn = AnimationUtils 
      .loadAnimation(this, R.anim.slide_right_in); 
    slideRightOut = AnimationUtils.loadAnimation(this, 
      R.anim.slide_right_out); 

    viewFlipper.setInAnimation(AnimationUtils.loadAnimation(this, 
      android.R.anim.fade_in)); 
    viewFlipper.setOutAnimation(AnimationUtils.loadAnimation(this, 
      android.R.anim.fade_out)); 

    iv.setImageDrawable(Drawable.createFromPath(ImageList 
      .get(currentIndex))); 
    System.gc(); 

    gestureDetector = new GestureDetector(new MyGestureDetector()); 
    gestureListener = new View.OnTouchListener() { 
     public boolean onTouch(View v, MotionEvent event) { 
      if (gestureDetector.onTouchEvent(event)) { 
       return true; 
      } 
      return false; 
     } 
    }; 

} 

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    super.onCreateOptionsMenu(menu); 

    int NONE = Menu.NONE; 
    menu.add(NONE, EXIT, NONE, "Exit"); 
    return true; 
} 

public boolean onOptionsItemSelected(MenuItem item) { 
    switch (item.getItemId()) { 
    case EXIT: 
     quit(); 
     break; 
    } 

    return super.onOptionsItemSelected(item); 
} 

protected void onPause() { 
    super.onPause(); 

    SharedPreferences indexPrefs = getSharedPreferences("currentIndex", 
      MODE_PRIVATE); 

    SharedPreferences.Editor indexEditor = indexPrefs.edit(); 
    indexEditor.putInt("currentIndex", currentIndex); 
    indexEditor.commit(); 
} 

protected void onResume() { 
    super.onResume(); 
    SharedPreferences indexPrefs = getSharedPreferences("currentIndex", MODE_PRIVATE); 
    if (indexPrefs.contains("currentIndex")) { 
     currentIndex = indexPrefs.getInt("currentIndex", 0); 
    } 
} 

private List<String> FindFiles() { 
    final List<String> tFileList = new ArrayList<String>(); 
    Resources resources = getResources(); 
    // array of valid image file extensions 
    String[] imageTypes = resources.getStringArray(R.array.image); 
    FilenameFilter[] filter = new FilenameFilter[imageTypes.length]; 

    int i = 0; 
    for (final String type : imageTypes) { 
     filter[i] = new FilenameFilter() { 
      public boolean accept(File dir, String name) { 
       return name.endsWith("." + type); 
      } 
     }; 
     i++; 
    } 

    FileUtils fileUtils = new FileUtils(); 
    File[] allMatchingFiles = fileUtils.listFilesAsArray(
      new File(DIRECTORY), filter, -1); 
    for (File f : allMatchingFiles) { 
     tFileList.add(f.getAbsolutePath()); 
    } 
    return tFileList; 
} 

public class FileUtils { 

    public void saveArray(String filename, List<String> output_field) { 
     try { 
      FileOutputStream fos = new FileOutputStream(filename); 
      GZIPOutputStream gzos = new GZIPOutputStream(fos); 
      ObjectOutputStream out = new ObjectOutputStream(gzos); 
      out.writeObject(output_field); 
      out.flush(); 
      out.close(); 
     } 
     catch (IOException e) { 
      e.getStackTrace(); 
     } 
     } 

     @SuppressWarnings("unchecked") 
    public List<String> loadArray(String filename) { 
      try { 
      FileInputStream fis = new FileInputStream(filename); 
      GZIPInputStream gzis = new GZIPInputStream(fis); 
      ObjectInputStream in = new ObjectInputStream(gzis); 
      List<String> read_field = (List<String>)in.readObject(); 
      in.close(); 
      return read_field; 
      } 
      catch (Exception e) { 
       e.getStackTrace(); 
      } 
      return null; 
     } 

    public File[] listFilesAsArray(File directory, FilenameFilter[] filter, 
      int recurse) { 
     Collection<File> files = listFiles(directory, filter, recurse); 

     File[] arr = new File[files.size()]; 
     return files.toArray(arr); 
    } 

    public Collection<File> listFiles(File directory, 
      FilenameFilter[] filter, int recurse) { 

     Vector<File> files = new Vector<File>(); 

     File[] entries = directory.listFiles(); 

     if (entries != null) { 
      for (File entry : entries) { 
       for (FilenameFilter filefilter : filter) { 
        if (filter == null 
          || filefilter 
            .accept(directory, entry.getName())) { 
         files.add(entry); 
         Log.v("ImageViewFlipper", "Added: " 
           + entry.getName()); 
        } 
       } 
       if ((recurse <= -1) || (recurse > 0 && entry.isDirectory())) { 
        recurse--; 
        files.addAll(listFiles(entry, filter, recurse)); 
        recurse++; 
       } 
      } 
     } 
     return files; 
    } 
} 

class MyGestureDetector extends SimpleOnGestureListener { 
    @Override 
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, 
      float velocityY) { 
     try { 
      if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH) 
       return false; 
      // right to left swipe 
      if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE 
        && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { 
       viewFlipper.setInAnimation(slideLeftIn); 
       viewFlipper.setOutAnimation(slideLeftOut); 

       if (currentIndex == maxIndex) { 
        currentIndex = 0; 
       } else { 
        currentIndex = currentIndex + 1; 
       } 
       if (currentView == 0) { 
        currentView = 1; 
        ImageView iv = (ImageView) findViewById(R.id.one); 
        iv.setImageDrawable(Drawable.createFromPath(ImageList 
          .get(currentIndex))); 
        System.gc(); 
       } else if (currentView == 1) { 
        currentView = 2; 
        ImageView iv = (ImageView) findViewById(R.id.two); 
        iv.setImageDrawable(Drawable.createFromPath(ImageList 
          .get(currentIndex))); 
        System.gc(); 
       } else { 
        currentView = 0; 
        ImageView iv = (ImageView) findViewById(R.id.zero); 
        iv.setImageDrawable(Drawable.createFromPath(ImageList 
          .get(currentIndex))); 
        System.gc(); 
       } 
       Log.v("ImageViewFlipper", "Current View: " + currentView); 
       viewFlipper.showNext(); 
      } else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE 
        && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { 
       viewFlipper.setInAnimation(slideRightIn); 
       viewFlipper.setOutAnimation(slideRightOut); 
       if (currentIndex == 0) { 
        currentIndex = maxIndex; 
       } else { 
        currentIndex = currentIndex - 1; 
       } 
       if (currentView == 0) { 
        currentView = 2; 
        ImageView iv = (ImageView) findViewById(R.id.two); 
        iv.setImageDrawable(Drawable.createFromPath(ImageList.get(currentIndex))); 
       } else if (currentView == 2) { 
        currentView = 1; 
        ImageView iv = (ImageView) findViewById(R.id.one); 
        iv.setImageDrawable(Drawable.createFromPath(ImageList.get(currentIndex))); 
       } else { 
        currentView = 0; 
        ImageView iv = (ImageView) findViewById(R.id.zero); 
        iv.setImageDrawable(Drawable.createFromPath(ImageList 
          .get(currentIndex))); 
       } 
       Log.v("ImageViewFlipper", "Current View: " + currentView); 
       viewFlipper.showPrevious(); 
      } 
     } catch (Exception e) { 
      // nothing 
     } 
     return false; 
    } 
} 

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    if (gestureDetector.onTouchEvent(event)) 
     return true; 
    else 
     return false; 
} 

public void quit() { 
    SharedPreferences indexPrefs = getSharedPreferences("currentIndex",MODE_PRIVATE); 

    SharedPreferences.Editor indexEditor = indexPrefs.edit(); 
    indexEditor.putInt("currentIndex", 0); 
    indexEditor.commit(); 
    File settings = new File(DATA_FILE); 
    settings.delete(); 
    finish(); 
    int pid = android.os.Process.myPid(); 
    android.os.Process.killProcess(pid); 
    System.exit(0); 
} 


@Override 
public void onDetachedFromWindow() { 
    try { 
     super.onDetachedFromWindow(); 
    } catch (IllegalArgumentException e) { 

    } 
    } 
@Override 
public void onConfigurationChanged(Configuration newConfig) { 
    super.onConfigurationChanged(newConfig); 




} 


@Override 
    protected void onDestroy() { 
    super.onDestroy(); 
    System.gc(); 
    } 

}

編輯(日誌目錄):

 01-05 15:56:38.049: I/Process(573): Sending signal. PID: 573 SIG: 9 
    01-05 15:59:38.389: D/dalvikvm(637): GC_EXTERNAL_ALLOC freed 64K, 52% free 2613K/5379K, external 1625K/2137K, paused 49ms 
     01-05 15:59:48.739: D/dalvikvm(637): GC_EXTERNAL_ALLOC freed 9K, 52% free 2634K/5379K, external 3139K/3903K, paused 53ms 
     01-05 15:59:49.070: D/szipinf(637): Initializing inflate state 
     01-05 16:00:02.489: V/currentIndex(637): Index: 1 
     01-05 16:00:02.791: D/dalvikvm(637): GC_EXTERNAL_ALLOC freed 57K, 50% free 2748K/5447K, external 5580K/5793K, paused 36ms 
     01-05 16:00:03.180: D/dalvikvm(637): GC_EXPLICIT freed 48K, 51% free 2700K/5447K, external 8692K/10740K, paused 38ms 
     01-05 16:00:04.670: D/dalvikvm(637): GC_EXTERNAL_ALLOC freed 8K, 50% free 2737K/5447K, external 8692K/10740K, paused 34ms 
     01-05 16:00:05.069: D/dalvikvm(637): GC_EXPLICIT freed 32K, 51% free 2705K/5447K, external 13317K/15365K, paused 54ms 
     01-05 16:00:05.069: V/ImageViewFlipper(637): Current View: 1 
     01-05 16:00:05.170: D/dalvikvm(637): GC_EXTERNAL_ALLOC freed <1K, 51% free 2705K/5447K, external 14817K/15365K, paused 33ms 
     01-05 16:00:19.109: D/dalvikvm(637): GC_EXTERNAL_ALLOC freed 5K, 50% free 2734K/5447K, external 14817K/16865K, paused 41ms 
     01-05 16:00:19.139: E/dalvikvm-heap(637): 4736340-byte external allocation too large for this process. 
     01-05 16:00:19.249: E/GraphicsJNI(637): VM won't let us allocate 4736340 bytes 
    01-05 16:00:19.249: D/dalvikvm(637): GC_FOR_MALLOC freed 0K, 50% free 2734K/5447K, external 14817K/16865K, paused 36ms 
    01-05 16:00:19.259: D/skia(637): --- decoder->decode returned false 
     01-05 16:00:19.259: D/AndroidRuntime(637): Shutting down VM 
     01-05 16:00:19.259: W/dalvikvm(637): threadid=1: thread exiting with uncaught exception (group=0x40015560) 
    01-05 16:00:19.270: E/AndroidRuntime(637): FATAL EXCEPTION: main 
     01-05 16:00:19.270: E/AndroidRuntime(637): java.lang.OutOfMemoryError: bitmap size exceeds VM budget 
     01-05 16:00:19.270: E/AndroidRuntime(637): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method) 
    01-05 16:00:19.270: E/AndroidRuntime(637):  at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:470) 
    01-05 16:00:19.270: E/AndroidRuntime(637):  at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:284) 
    01-05 16:00:19.270: E/AndroidRuntime(637):  at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:309) 
    01-05 16:00:19.270: E/AndroidRuntime(637):  at android.graphics.drawable.Drawable.createFromPath(Drawable.java:800) 
    01-05 16:00:19.270: E/AndroidRuntime(637):  at com.edubridge.ImageViewFlipper$MyGestureDetector.onFling(ImageViewFlipper.java:307) 
    01-05 16:00:19.270: E/AndroidRuntime(637):  at android.view.GestureDetector.onTouchEvent(GestureDetector.java:568) 
    01-05 16:00:19.270: E/AndroidRuntime(637):  at com.edubridge.ImageViewFlipper.onTouchEvent(ImageViewFlipper.java:354) 
    01-05 16:00:19.270: E/AndroidRuntime(637):  at android.app.Activity.dispatchTouchEvent(Activity.java:2099) 
    01-05 16:00:19.270: E/AndroidRuntime(637):  at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1675) 
    01-05 16:00:19.270: E/AndroidRuntime(637):  at android.view.ViewRoot.deliverPointerEvent(ViewRoot.java:2194) 
    01-05 16:00:19.270: E/AndroidRuntime(637):  at android.view.ViewRoot.handleMessage(ViewRoot.java:1878) 
    01-05 16:00:19.270: E/AndroidRuntime(637):  at android.os.Handler.dispatchMessage(Handler.java:99) 
     01-05 16:00:19.270: E/AndroidRuntime(637): at android.os.Looper.loop(Looper.java:123) 
     01-05 16:00:19.270: E/AndroidRuntime(637): at android.app.ActivityThread.main(ActivityThread.java:3683) 
     01-05 16:00:19.270: E/AndroidRuntime(637): at java.lang.reflect.Method.invokeNative(Native Method) 
     01-05 16:00:19.270: E/AndroidRuntime(637): at java.lang.reflect.Method.invoke(Method.java:507) 
     01-05 16:00:19.270: E/AndroidRuntime(637): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839) 
     01-05 16:00:19.270: E/AndroidRuntime(637): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) 
     01-05 16:00:19.270: E/AndroidRuntime(637): at dalvik.system.NativeStart.main(Native Method) 
     01-05 16:01:27.619: I/Process(637): Sending signal. PID: 637 SIG: 9 
+1

你可以看看http://stackoverflow.com/a/823966/477878 –

回答

2

你需要按比例縮小圖片消耗更少的內存,看看this答案,看看它縮小的正確方法,同樣當你需要知道圖像的寬度和高度而不加載到內存時使用此代碼,

BitmapFactory.Options bitmapOptions = new BitmapFactory.Options(); 
bitmapOptions.inJustDecodeBounds = true; 
BitmapFactory.decodeStream(inputStream, null, bitmapOptions); 
int imageWidth = bitmapOptions.outWidth; 
int imageHeight = bitmapOptions.outHeight; 
inputStream.close(); 
+1

謝謝你的代碼讓我提示!我將在答案部分發佈下面的正確答案。 – Skynet

0
 if (currentView == 0) { 
        currentView = 1; 
        BitmapFactory.Options opts = new BitmapFactory.Options(); 
        //The max size of any dimension (height or width) is 400 px 
        opts.inSampleSize = OG; 
        //Drawable X = Drawable.createFromPath(ImageList.get(currentIndex)); 
        Bitmap bmp = BitmapFactory.decodeFile(ImageList.get(currentIndex), opts); 

        ImageView iv = (ImageView) findViewById(R.id.one); 
        iv.setImageBitmap(bmp); 
        System.gc(); 
        //ImageView iv = (ImageView) findViewById(R.id.one); 
        //iv.setImageDrawable(Drawable.createFromPath(ImageList.get(currentIndex))); 
        //System.gc(); 
相關問題