CrimsonX CrimsonX - 21 days ago 6
Android Question

Replacing call to setImageResource() with setImageBitmap to reduce hiccup?

Android's setImageResource() documentation states:


This does Bitmap reading and decoding on the UI thread, which can
cause a latency hiccup. If that's a concern, consider using
setImageDrawable(android.graphics.drawable.Drawable) or
setImageBitmap(android.graphics.Bitmap) and BitmapFactory instead.


I'm looking to solve this exact issue in my example application. I think I'm supposed to "read between the lines" here and and replace my call from :

((ImageView) rootView.findViewById(R.id.screen_image)).setImageResource(imageId);


to instead call

InputStream is = this.getResources().openRawResource(imageId);
Bitmap imageBitmap = BitmapFactory.decodeStream(is);
((ImageView) rootView.findViewById(R.id.screen_image)).setImageBitmap(imageBitmap);


but do this from within another thread, by using something like an
AsyncTask
-

Am I correct in my understanding, or is there a simpler solution?

Update:

It looks like there is an entire section on displaying bitmaps efficiently on developer.android.com - I'm investigating that now.

Answer

The simplest way to solve this issue is create a worker thread as described in the thread & process documentation. As it mentions, async task can be used to replace this for more complex code. the final solution was to change my code in the OnCreateView() method, replacing the original laggy code:

 final View rootView = inflater.inflate(R.layout.fragment_screen, container, false);
 int i = getArguments().getInt(ARG_PANEL_NUMBER);
 String panel = getResources().getStringArray(R.array.panel_array)[i];
 int imageId = getResources().getIdentifier(panel.toLowerCase(Locale.getDefault()),
                "drawable", getActivity().getPackageName());

 ((ImageView) rootView.findViewById(R.id.screen_image)).setImageDrawable(getResources().getDrawable(imageId));

with a new background thread:

final View rootView = inflater.inflate(R.layout.fragment_screen, container, false);

// Load image in a separate thread to ensure navigation drawer animation is smooth.
// Replace with Async Task if necessary
    new Thread(new Runnable() {
        public void run() {
            int i = getArguments().getInt(ARG_PANEL_NUMBER);
            final String panel = getResources().getStringArray(R.array.panel_array)[i];

            int imageId = getResources().getIdentifier(panel.toLowerCase(Locale.getDefault()),
                    "drawable", getActivity().getPackageName());

            InputStream is = getActivity().getResources().openRawResource(imageId);
            final Bitmap imageBitmap = BitmapFactory.decodeStream(is);
            rootView.post( new Runnable() {
                public void run() {
                    ((ImageView) rootView.findViewById(R.id.screen_image)).setImageBitmap(imageBitmap);
                    getActivity().setTitle(panel);
                }
            });
        }

    }).start();

As described in the documentation above, using an async task is more extensible and maintainable if this code grows to be too large.

Comments