2

Android 的setImageResource() 文档指出:

这会在 UI 线程上进行位图读取和解码,这可能会导致延迟打嗝。如果这是一个问题,请考虑改用 setImageDrawable(android.graphics.drawable.Drawable) 或 setImageBitmap(android.graphics.Bitmap) 和 BitmapFactory。

我希望在我的示例应用程序中解决这个确切的问题。我想我应该在这里“阅读字里行间”并替换我的电话:

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

改为调用

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

但是在另一个线程中这样做,通过使用类似的东西AsyncTask-

我的理解是正确的,还是有更简单的解决方案?

更新:

在 developer.android.com 上似乎有一整节关于有效地显示位图- 我现在正在调查。

4

3 回答 3

4

解决此问题的最简单方法是创建一个工作线程,如线程和进程文档中所述。正如它所提到的,异步任务可用于将其替换为更复杂的代码。最终的解决方案是在方法中更改我的代码OnCreateView(),替换原来的滞后代码:

 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));

使用新的后台线程:

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();

如上面文档中所述,如果此代码变得太大,则使用异步任务更具可扩展性和可维护性。

于 2013-07-22T18:24:07.447 回答
2

setImageResource() 方法有点慢,因为它在 UI 线程上进行解码,我们可以使用工作线程或 AsyncTaks 来解决这个问题,但是可以使用一个简单且现成的解决方案。哪个是 Glide 库。您只需要将它的依赖项添加到您的 gradle 文件中,如下所示:

compile 'com.github.bumptech.glide:glide:3.7.0'

然后使用它的 id 将可绘制图像设置为:

Glide.with(context).load(bImage).into(tipImages);

也可能是像毕加索这样的其他图像库提供了这个选项,但我在这里使用了 Glide。

于 2016-11-12T17:41:54.353 回答
0

我不会读这么多。我解释的方式就是使用:

setImageDrawable(getResources().getDrawable(R.id.yourid);

我确实在您的代码中看到了另一个可能导致打嗝的问题。您正在调用 rootView.findViewById。FindViewById 是一个昂贵的调用,所以你应该只做一次。如果此代码全部发生在您的构造函数中,那么没关系,但如果它在列表适配器更新行方法中,例如,这可能会导致延迟!执行一次 findViewById 并将视图分配给成员变量。

于 2013-07-11T22:51:13.760 回答