Search code examples
androidlistviewmemorymupdf

Usingt Mupdf and a list view in two seperate activities eventually runs out of memory


I have an app that uses a list adapter to generate a list of items that when clicked us Mupdf to view the item (a pdf)

If I bounce back and forth between views I will eventually run out of memory and crash. How do I make sure that each view is starting with as much memory as possible so that I do not crash the app.

the list view adapter is pretty straightforward:

public class PosterListAdapter extends BaseAdapter {

        private final ArrayList<Poster> listItems;
        private final ArrayList<PosterCategory> categoryList;

        private final LayoutInflater inflater;

        public PosterListAdapter(ArrayList<Poster> listItems, ArrayList<PosterCategory> categoryItems, LayoutInflater inflater) {
            this.listItems = listItems;
            this.categoryList = categoryItems;
            this.inflater = inflater;
        }       


        @Override
        public int getCount() {
            //Log.d("getCount", String.valueOf(this.listItems.size()));
            return this.listItems.size();               
        }

        @Override
        public Poster getItem(int i) {

            return this.listItems.get(i);
        }

        public PosterCategory getCItem(int i){

            return this.categoryList.get(i);
        }

        @Override
        public long getItemId(int i) {
            return 0;
        }

        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {

            if (view == null) {
                view = inflater.inflate(R.layout.catalog_list_fragment, viewGroup, false);
            }
            TextView posterTitle = ((TextView) view.findViewById(R.id.poster_title));
            TextView posterAuthor = ((TextView) view.findViewById(R.id.poster_author));
            TextView posterSynopsis = ((TextView) view.findViewById(R.id.poster_synopsis));
            TextView posterCategory = ((TextView) view.findViewById(R.id.poster_category));
            TextView posterNumber = ((TextView) view.findViewById(R.id.poster_number));
            ImageView imageView = ((ImageView) view.findViewById(R.id.poster_thumb));

            //LayoutParams params = (LayoutParams) imageView.getLayoutParams();

            Poster item = this.listItems.get(i);

            String filename = item.getPosterFilename();
            posterAuthor.setText(item.getPresenterFname()+' '+item.getPresenterLname());
            posterTitle.setText(item.getPosterTitle());
            posterSynopsis.setText(item.getPosterSynopsis());
            posterNumber.setText("Poster: "+String.valueOf(item.getPosterNumber()));

            //Log.d("PosterNumber", String.valueOf(item.getPosterNumber()));

            int catId = item.getCatID();

            posterCategory.setText(getCategoryById(categoryList, catId));

            File imgFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath(), filename+".png");
            //File imgFile = getBaseContext().getFileStreamPath(filename+".png");

            Bitmap bmp = BitmapFactory.decodeFile(imgFile.toString());
            //int newWidth = 500;
            //Bitmap sizedBMP = getResizedBitmap(bmp, newWidth);

            imageView.setImageBitmap(bmp);

            return view;
        }
    }

Solution

  • The most likely explanation is that you are leaking memory somewhere.

    While Java does a pretty good job of recovering memory owned purely by Java code (using Garbage Collection), MuPDF does most of it's work in C. This means that care needs to be taken to call the MuPDF APIs in the correct way to avoid leaks.

    You have not given us enough information in your question to see how you are calling MuPDF, so it's not really possible to check your code for sanity.

    (Also, before you embark on a project that uses MuPDF, please ensure you have read and understand the License terms. The only free license for MuPDF is the GNU APGL, and this may not be suitable for your app. Commercial licenses are available of course. Better to realise this up front!)