问题
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.
回答1:
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.
回答2:
setImageResource() method is bit slow because it does decoding on UI thread, We can solve this problem using worker thread or AsyncTaks, but a simple and ready made solution is available for that. Which is Glide library. You just need to add it's dependency to your gradle file as:
compile 'com.github.bumptech.glide:glide:3.7.0'
and then set drawable image using it's id as:
Glide.with(context).load(bImage).into(tipImages);
Also may be other image libraries like Picasso provide this option, but i used Glide here.
回答3:
I wouldn't read into it so much. The way I interpret that is to just use:
setImageDrawable(getResources().getDrawable(R.id.yourid);
I do see another issue in your code that may be causing hiccups. You are calling rootView.findViewById. FindViewById is an expensive call, so you should only do it once. If this code is all happening in your constructor then it's ok, but if it's in a List adapter update row method for example, this could cause lag! Do your findViewById once and assign the view to a member variable.
来源:https://stackoverflow.com/questions/17604423/replacing-call-to-setimageresource-with-setimagebitmap-to-reduce-hiccup