0

下面的代码给java.lang.OutOfMemoryError:位图超过VM预算Android图库问题,内存

我正在写一个应用程序通过一系列图片,这些都是全屏的刷卡。我知道我一起加载所有图像多数民众赞成什么造成的问题,但我不知道如何克服这个问题。有人请帮忙。

package akash.gal; 

    import android.app.Activity; 
    import android.content.Context; 
    import android.content.res.TypedArray; 
    import android.os.Bundle; 
    import android.util.DisplayMetrics; 
    import android.view.View; 
    import android.view.ViewGroup; 
    import android.widget.BaseAdapter; 
    import android.widget.Gallery; 
    import android.widget.ImageView; 

    public class GalActivity extends Activity { 
    /** Called when the activity is first created. */ 
    Integer imageids[]={R.drawable.one,R.drawable.two,R.drawable.three}; 
    @Override 

    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     Gallery gallery=(Gallery) findViewById(R.id.gallery1); 
     gallery.setAdapter(new ImageAdapter(this)); 
    } 
    public class ImageAdapter extends BaseAdapter{ 

    private Context context; 
    private int itemBackground; 
    public ImageAdapter(Context c) 
    { 
     context=c; 
     TypedArray a=obtainStyledAttributes(R.styleable.Gallery1); 
     itemBackground=a.getResourceId(R.styleable.Gallery1_android_galleryItemBackground,0); 
     a.recycle(); 
    } 
     public int getCount() { 
      // TODO Auto-generated method stub 
      return imageids.length; 
     } 

     public Object getItem(int arg0) { 
      // TODO Auto-generated method stub 
      return arg0; 
     } 

     public long getItemId(int arg0) { 
      // TODO Auto-generated method stub 
      return arg0; 
     } 

     public View getView(int arg0, View arg1, ViewGroup arg2) { 
      // TODO Auto-generated method stub 
      ImageView imageView=new ImageView(context); 
      imageView.setImageResource(imageids[arg0]); 
      imageView.setScaleType(ImageView.ScaleType.FIT_XY); 
      DisplayMetrics dm=new DisplayMetrics(); 
      getWindowManager().getDefaultDisplay().getMetrics(dm); 
      imageView.setLayoutParams(new Gallery.LayoutParams(dm.widthPixels,dm.heightPixels)); 
      imageView.setBackgroundResource(itemBackground); 
      return imageView; 

     } 
} 
} 
+0

https://github.com/nostra13/Android-Universal-Image-Loader –

回答

1

在主要活动: -

public class Main extends Activity { 

    String mImagesPath; 

    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     mImagesPath = this.getFilesDir().getParent() + "/images/"; 
     createImagesDir(mImagesPath); 
     copyImagesToStorage(); 
     loadGridView(); 
    } 

    /** 
    * Method handles the logic for setting the adapter for the gridview 
    */ 
    private void loadGridView(){ 

     GridView lLazyGrid = (GridView) this.findViewById(R.id.gridview); 
     try { 
      LazyImageAdapter lLazyAdapter = new LazyImageAdapter(this.getApplicationContext(), 
        null, 
        mImagesPath); 
      lLazyGrid.setAdapter(lLazyAdapter); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

    } 

    /** 
    * Copy images from assets to storage 
    */ 
    private void copyImagesToStorage(){ 
     AssetManager lAssetManager = getAssets(); 
     String[] lFiles = null; 
     String lTag = "copyImageFail"; 

     try { 
      // get all of the files in the assets directory 
      lFiles = lAssetManager.list(""); 
     } catch (IOException e) { 
      Log.e(lTag, e.getMessage()); 
     } 


     for(int i=0; i<lFiles.length; i++) { 
      // We have a file to copy 


      try { 

       // copy the file 
       copyFile(lFiles[i], mImagesPath + lFiles[i]); 
      } catch(Exception e) { 
       Log.e(lTag, e.getMessage()); 
      }  
     } 
    } 

    /** 
    * Method copies the contents of one stream to another 
    * @param aIn stream to copy from 
    * @param aOut stream to copy to 
    * @throws IOException 
    */ 
    private void copyFile(String aIn, String aOut) throws IOException { 
     byte[] lBuffer = new byte[1024]; 
     int lRead; 
     final int lOffset = 0; 

     // create an in and out stream 
     InputStream lIn = getAssets().open(aIn); 
     OutputStream lOut = new FileOutputStream(aOut); 

     // Copy contents while there is data 
     while((lRead = lIn.read(lBuffer)) != -1){ 
      lOut.write(lBuffer, lOffset, lRead); 
     } 

     // clean up after our streams 
     lIn.close(); 
     lIn = null; 
     lOut.flush(); 
     lOut.close(); 
     lOut = null; 
    } 

    /** 
    * Create the directory specified at aPath if it does not exist 
    * @param aPath directory to check for and create 
    */ 
    private void createImagesDir(String aPath){ 
     File lDir = new File(aPath); 
     if(!lDir.exists()){ 
      lDir.mkdir(); 
     } 
    } 
} 

============================== =======

在ImageLoader的类别:

public class ImageLoader extends Thread { 

    public interface ImageLoadListener { 

     void handleImageLoaded(ViewSwitcher aViewSwitcher, ImageView aImageView, Bitmap aBitmap); 
    } 

    private static final String TAG = ImageLoader.class.getSimpleName(); 
    ImageLoadListener mListener = null; 
    private Handler handler; 

    /** 
    * Image loader takes an object that extends ImageLoadListener 
    * @param lListener 
    */ 
    ImageLoader(ImageLoadListener lListener){ 
     mListener = lListener; 
    } 

    @Override 
    public void run() { 
     try { 

      // preparing a looper on current thread   
      // the current thread is being detected implicitly 
      Looper.prepare(); 

      // Looper gets attached to the current thread by default 
      handler = new Handler(); 

      Looper.loop(); 
      // Thread will start 

     } catch (Throwable t) { 
      Log.e(TAG, "ImageLoader halted due to a error: ", t); 
     } 
    } 

    /** 
    * Method stops the looper and thus the thread 
    */ 
    public synchronized void stopThread() { 

     // Use the handler to schedule a quit on the looper 
     handler.post(new Runnable() { 

      public void run() { 
       // This runs on the ImageLoader thread 
       Log.i(TAG, "DownloadThread loop quitting by request"); 

       Looper.myLooper().quit(); 
      } 
     }); 
    } 

    /** 
    * Method queues the image at path to load 
    * Note that the actual loading takes place in the UI thread 
    * the ImageView and ViewSwitcher are just references for the 
    * UI thread. 
    * @param aPath  - Path where the bitmap is located to load 
    * @param aImageView - The ImageView the UI thread will load 
    * @param aViewSwitcher - The ViewSwitcher that needs to display the imageview 
    */ 
    public synchronized void queueImageLoad(
      final String aPath, 
      final ImageView aImageView, 
      final ViewSwitcher aViewSwitcher) { 

     // Wrap DownloadTask into another Runnable to track the statistics 
     handler.post(new Runnable() { 
      public void run() { 
       try { 

        synchronized (aImageView){ 
         // make sure this thread is the only one performing activities on 
         // this imageview 
         BitmapFactory.Options lOptions = new BitmapFactory.Options(); 
         lOptions.inSampleSize = 1; 
         Bitmap lBitmap = BitmapFactory.decodeFile(aPath, lOptions); 
         //aImage.setImageBitmap(lBitmap); 

         // Load the image here 
         signalUI(aViewSwitcher, aImageView, lBitmap); 
        } 
       } 
       catch(Exception e){ 
        e.printStackTrace(); 
       } 
      } 
     }); 
    } 

    /** 
    * Method is called when the bitmap is loaded. The UI thread adds the bitmap to the imageview. 
    * @param aViewSwitcher - The ViewSwitcher that needs to display the imageview 
    * @param aImageView - The ImageView the UI thread will load 
    * @param aImage - The Bitmap that gets loaded into the ImageView 
    */ 
    private void signalUI(
      ViewSwitcher aViewSwitcher, 
      ImageView aImageView, 
      Bitmap aImage){ 

     if(mListener != null){ 
      // we have an object that implements ImageLoadListener 

      mListener.handleImageLoaded(aViewSwitcher, aImageView, aImage); 
     } 
    } 

} 

============================ ==========

LazyImageAdapter:

public class LazyImageAdapter extends BaseAdapter implements ImageLoadListener { 

    private static final int PROGRESSBARINDEX = 0; 
    private static final int IMAGEVIEWINDEX = 1; 


    private Context mContext = null; 
    private OnClickListener mItemClickListener; 
    private Handler mHandler; 
    private ImageLoader mImageLoader = null; 
    private File mDirectory; 

    /** 
    * Lazy loading image adapter 
    * @param aContext 
    * @param lClickListener click listener to attach to each item 
    * @param lPath the path where the images are located 
    * @throws Exception when path can't be read from or is not a valid directory 
    */ 
    public LazyImageAdapter(
      Context aContext, 
      OnClickListener lClickListener, 
      String lPath 
     ) throws Exception { 

     mContext = aContext; 
     mItemClickListener = lClickListener; 
     mDirectory = new File(lPath); 

     // Do some error checking 
     if(!mDirectory.canRead()){ 
      throw new Exception("Can't read this path"); 
     } 
     else if(!mDirectory.isDirectory()){ 
      throw new Exception("Path is a not a directory"); 
     } 

     mImageLoader = new ImageLoader(this); 
     mImageLoader.start(); 
     mHandler = new Handler(); 

    } 

    @Override 
    protected void finalize() throws Throwable { 
     // TODO Auto-generated method stub 
     super.finalize(); 

     // stop the thread we started 
     mImageLoader.stopThread(); 
    } 

    public int getCount() { 
     return mDirectory.listFiles().length; 
    } 

    public Object getItem(int aPosition) { 
     String lPath = null; 
     File []lFiles = mDirectory.listFiles(); 
     if(aPosition < lFiles.length){ 
      lPath = mDirectory.listFiles()[aPosition].getAbsolutePath(); 
     } 

     return lPath; 
    } 

    public long getItemId(int arg0) { 
     // TODO Auto-generated method stub 
     return 0; 
    } 

    public View getView(final int aPosition, View aConvertView, ViewGroup parent) { 
     final ViewSwitcher lViewSwitcher; 
     String lPath = (String)getItem(aPosition); 

     // logic for conserving resources see google video on making your ui fast 
     // and responsive 
     if (null == aConvertView) { 
      lViewSwitcher = new ViewSwitcher(mContext); 
      lViewSwitcher.setPadding(8, 8, 8, 8); 

      ProgressBar lProgress = new ProgressBar(mContext); 
      lProgress.setLayoutParams(new ViewSwitcher.LayoutParams(80, 80)); 
      lViewSwitcher.addView(lProgress); 
      ImageView lImage = new ImageView(mContext); 
      lImage.setLayoutParams(new ViewSwitcher.LayoutParams(100, 100)); 

      lViewSwitcher.addView(lImage); 

      // attach the onclick listener 
      lViewSwitcher.setOnClickListener(mItemClickListener); 

     } else { 
      lViewSwitcher = (ViewSwitcher) aConvertView; 
     } 


     ViewTagInformation lTagHolder = (ViewTagInformation) lViewSwitcher 
       .getTag(); 

     if (lTagHolder == null || 
      !lTagHolder.aImagePath.equals(lPath)) { 
      // The Tagholder is null meaning this is a first time load 
      // or this view is being recycled with a different image 

      // Create a ViewTag to store information for later 
      ViewTagInformation lNewTag = new ViewTagInformation(); 
      lNewTag.aImagePath = lPath; 
      lViewSwitcher.setTag(lNewTag); 

      // Grab the image view 
      // Have the progress bar display 
      // Then queue the image loading 
      ImageView lImageView = (ImageView) lViewSwitcher.getChildAt(1); 
      lViewSwitcher.setDisplayedChild(PROGRESSBARINDEX); 
      mImageLoader.queueImageLoad(lPath, lImageView, lViewSwitcher); 


     } 

     return lViewSwitcher; 
    } 


    public void handleImageLoaded(
      final ViewSwitcher aViewSwitcher, 
      final ImageView aImageView, 
      final Bitmap aBitmap) { 

     // The enqueue the following in the UI thread 
     mHandler.post(new Runnable() { 
      public void run() { 

       // set the bitmap in the ImageView 
       aImageView.setImageBitmap(aBitmap); 

       // explicitly tell the view switcher to show the second view 
       aViewSwitcher.setDisplayedChild(IMAGEVIEWINDEX); 
      } 
     }); 

    } 


} 

/** 
* View holder pattern as described in google sample code 
* we may want to add more attributes to this if the path was 
* say being stored in a sqlite database 
* @author bacaj 
*/ 
class ViewTagInformation { 
    String aImagePath; 
} 
+0

ü也可以reffer此链接更多的例子:https://github.com/thest1/LazyList –