Pregunta

I've setup a viewPager which should show around 50 images with a resolution of 1500,2100px. The images are provided by the user self. So I need to downscale the images which I do with this bit of code:

WindowManager wm = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
    Display display = wm.getDefaultDisplay();
    Point size = new Point();
    display.getSize(size);
    int width = size.x;
    int height = size.y;
    //imageFile is a string to the image location.
    Bitmap bm = BitmapFactory.decodeFile(imagefile);
    Bitmap scaledBitmap = Bitmap.createScaledBitmap(bm, width, height, true);

When the image is downscaled I add it to the viewpager in a arrayList which works perfectly with only a few images. But now I need to load in 50 images, how am I supposed to do this? I'm getting outOfMemory errors, even after I downscaled the images.

The images are added with this code (to the ViewPager):

    @Override
public Object instantiateItem(ViewGroup container, int position) {
    ImageView imageView = new ImageView(context);
    //int padding = context.getResources().getDimensionPixelSize(R.dimen.padding_medium);
    //imageView.setPadding(padding, padding, padding, padding);
    imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
    //imageView.setImageResource(pages.get(position));
    imageView.setImageBitmap(pages.get(position));
    ((ViewPager) container).addView(imageView, 0);
    return imageView;
}

I hope to get a good suggestion. I was thinking myself of loading only a few images and adding them dynamicly, but I don't know how I can destroy loaded images once I don't need them anymore. I'm open to any suggestions!

¿Fue útil?

Solución

Try using Fragments and FragmentPagerAdapter in ViewPager. In this method only 3 fragments(pages) are stored in the ViewPager Stack at any given point of time.

  1. Previous Page
  2. Current Page
  3. Next Page

Ex:- If you are in the 2nd page of the ViewPager the ViewPager stack contains Page1, Page2 and Page3. If you swipe from Page 2 to Page 3, Page 4 is loaded on to the stack and Page 1 is removed from the stack.

Using this in your app will save a lot of memory as only 3 images will be present in the memory at any given time.

This has been explained well in the developer page http://developer.android.com/training/displaying-bitmaps/display-bitmap.html

An example of this implementation -

public class MainActivity extends FragmentActivity {


SectionsPagerAdapter mSectionsPagerAdapter;


ViewPager mViewPager;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Create the adapter that will return a fragment for each of the three
    // primary sections of the app.
    mSectionsPagerAdapter = new SectionsPagerAdapter(
            getSupportFragmentManager());

    // Set up the ViewPager with the sections adapter.
    mViewPager = (ViewPager) findViewById(R.id.pager);
    mViewPager.setAdapter(mSectionsPagerAdapter);

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

/**
 * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
 * one of the sections/tabs/pages.
 */
public class SectionsPagerAdapter extends FragmentPagerAdapter {

    public SectionsPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        // getItem is called to instantiate the fragment for the given page.
        // Return a DummySectionFragment (defined as a static inner class
        // below) with the page number as its lone argument.
        Fragment fragment = new DummySectionFragment();
        Bundle args = new Bundle();
        args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, position + 1);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public int getCount() {
        // Show 3 total pages.
        return 3;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        Locale l = Locale.getDefault();
        switch (position) {
        case 0:
            return getString(R.string.title_section1).toUpperCase(l);
        case 1:
            return getString(R.string.title_section2).toUpperCase(l);
        case 2:
            return getString(R.string.title_section3).toUpperCase(l);
        }
        return null;
    }
}

/**
 * A dummy fragment representing a section of the app, but that simply
 * displays dummy text.
 */
public static class DummySectionFragment extends Fragment {
    /**
     * The fragment argument representing the section number for this
     * fragment.
     */
    public static final String ARG_SECTION_NUMBER = "section_number";

    public DummySectionFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_main_dummy,
                container, false);
        TextView dummyTextView = (TextView) rootView
                .findViewById(R.id.section_label);
        dummyTextView.setText(Integer.toString(getArguments().getInt(
                ARG_SECTION_NUMBER)));
        return rootView;
    }
}

You will have to integrate this code with your code. Let me know if you need any further help!:)

Otros consejos

Make use of BitmapFactory.Options to load scaled down version of image into memory.

You can refer this BitmapFactory.Options

Make use of inSampleSize, set its value to greater than 1.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top