0

次のコードはjava.lang.OutOfMemoryErrorを与えます:ビットマップがVMバジェットを超えています

すべて全画面表示の一連の画像をスワイプするアプリを作成しています。私はすべての画像を一緒にロードしていることを知っていますが、それが問題の原因ですが、この問題を克服する方法がわかりません。誰か助けてください。

  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;

        }
}
}
4

1 に答える 1

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;
}
于 2012-07-04T10:41:06.340 に答える