【问题标题】:Activity runs slow with a couple of ImageView-s使用几个 ImageView-s 时活动运行缓慢
【发布时间】:2016-02-05 10:58:03
【问题描述】:

我有一个总共包含 4 张图片的活动。它们都与 1080x1920 设备的分辨率相匹配。当我使用这些图像运行活动时,这些图像通过 XML 直接加载到我的活动中,它在我的 Genymotion 模拟器中运行非常慢,而在真正的 Android 设备上运行滞后

这是设置:

<android.support.design.widget.AppBarLayout
...>
<android.support.design.widget.CollapsingToolbarLayout
...>
<LinearLayout
            android:layout_width="match_parent"
            android:layout_height="200dp"
            android:orientation="vertical"
            app:layout_collapseMode="parallax">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:id="@+id/imageView"
                android:src="@drawable/shot_header"
                android:scaleType="centerCrop" />

 </LinearLayout>
 <android.support.v7.widget.Toolbar
            .../>
 </android.support.design.widget.CollapsingToolbarLayout>
 </android.support.design.widget.AppBarLayout>

第一张图片位于 CollapsingToolbar 布局中。图片的分辨率为 1080x649 PNG。

内容活动:
此图像填充父宽度。其分辨率为 1080x772 PNG。

 <ImageView
    android:layout_width="match_parent"
    android:layout_height="250dp"
    android:id="@+id/main_image"
    android:layout_below="@+id/shot_error_field"
    android:src="@drawable/forehand_midpng"
    android:adjustViewBounds="true"
    android:scaleType="centerCrop"
    android:layout_marginTop="15dp"/>

另外 2 张图片在 LinearLayout 中,它们的分辨率为 500x399

<LinearLayout
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_below="@+id/main_image">

    <ImageView
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:id="@+id/imageView3"
        android:src="@drawable/forehand_mid_wrong"
        android:layout_weight="1"/>

    <View
        android:layout_width="0dp"
        android:layout_height="1dp"
        android:layout_weight="1" >
    </View>

    <ImageView
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:id="@+id/imageView4"
        android:src="@drawable/forehand_mid_wrong"
        android:layout_weight="1"/>
</LinearLayout>

总而言之,我有一个包含 4 个 ImageView 的活动,其中填充了适当大小的图像,这对于现代 Android 设备应该没有问题。问题是由于高内存消耗,此活动运行非常缓慢且滞后。

难道我做错了什么?如何进一步优化这些图像?

我查看了其他线程-out of memory issue,但似乎没有人提出解决此类问题的方法。

【问题讨论】:

  • ImageView 一般不喜欢大图。
  • 你试过android:largeHeap="true"吗?这是不推荐的,但如果没有任何效果,它可能会有所帮助。
  • 问题是图像分辨率..请调整大小
  • 如果 ImageView 不喜欢图片,那么 Facebook 应用程序如何运行?
  • @BhaveshRangani 如何为每个设备动态调整大小?

标签: android performance imageview


【解决方案1】:

问题是图像的resolution,如果您可以使用图像的reduce resolution,则可以正常工作,这里有一些减少image resolution 和大小的示例。

如果你传递位图的宽度和高度,那么使用下面的函数。

    public Bitmap getResizedBitmap(Bitmap image, int bitmapWidth,
            int bitmapHeight) {
        return Bitmap.createScaledBitmap(image, bitmapWidth, bitmapHeight,
                true);
    } 

如果您希望位图比例相同并减小位图大小。然后传递您的最大尺寸位图。你可以使用这个功能

public Bitmap getResizedBitmap(Bitmap image, int maxSize) {
    int width = image.getWidth();
    int height = image.getHeight();

    float bitmapRatio = (float)width / (float) height;
    if (bitmapRatio > 0) {
        width = maxSize;
        height = (int) (width / bitmapRatio);
    } else {
        height = maxSize;
        width = (int) (height * bitmapRatio);
    }
    return Bitmap.createScaledBitmap(image, width, height, true);
}

或者如果您使用可绘制资源,则使用此方法

public Drawable resizeImage(int imageResource) {// R.drawable.large_image
    // Get device dimensions
    Display display = getWindowManager().getDefaultDisplay();
    double deviceWidth = display.getWidth();

    BitmapDrawable bd = (BitmapDrawable) this.getResources().getDrawable(
            imageResource);
    double imageHeight = bd.getBitmap().getHeight();
    double imageWidth = bd.getBitmap().getWidth();

    double ratio = deviceWidth / imageWidth;
    int newImageHeight = (int) (imageHeight * ratio);

    Bitmap bMap = BitmapFactory.decodeResource(getResources(), imageResource);
    Drawable drawable = new BitmapDrawable(this.getResources(),
            getResizedBitmap(bMap, newImageHeight, (int) deviceWidth));

    return drawable;
}

/************************ Resize Bitmap *********************************/
public Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth) {

    int width = bm.getWidth();
    int height = bm.getHeight();

    float scaleWidth = ((float) newWidth) / width;
    float scaleHeight = ((float) newHeight) / height;

    // create a matrix for the manipulation
    Matrix matrix = new Matrix();

    // resize the bit map
    matrix.postScale(scaleWidth, scaleHeight);

    // recreate the new Bitmap
    Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height,
            matrix, false);

    return resizedBitmap;
}

【讨论】:

  • 太棒了! resizeImage() 方法完美运行
  • 该死的,非常感谢resizeImage()函数人!让我的活动在巨大的背景下运行得非常流畅。
【解决方案2】:

实际上这应该不是问题,而且这些图像不会太大,不会让您手机迟钝。看看您在应用程序中的其他内容,可能在 UI 线程中存在一些繁重的操作(如 DB 写入/读取、API 请求)。

如果没有此类操作,并且您发现性能存在此类问题,请尝试通过某些库(例如 Picasso)设置这些图像。

Gradle 依赖:

compile 'com.squareup.picasso:picasso:2.4.0'

代码将如下所示:

Picasso.with(this).load(R.drawable.my_image).into(toolbar);

【讨论】:

    【解决方案3】:

    试试

    1. 一定要缩小图片大小。
    2. 尽可能缓存图片。
    3. 在不同的线程上下载图像。存储一个 HashMap 会 让你轻松

    当你得到图片 url 列表时,遍历它们:

    pictures.put(id,view);
            try{
                FileInputStream in = openFileInput(id);
                Bitmap bitmap = null;
                bitmap = BitmapFactory.decodeStream(in, null, null);
            view.setImageBitmap(bitmap);
            }catch(Exception e){
                new Thread(new PictureGetter(this,mHandler,id)).start();
            }
    

    更新图像视图的代码:

    if(id!=null){
            ImageView iv = pictures.get(id);
            if(iv!=null){
                try{
                    FileInputStream in = openFileInput(id);
                    Bitmap bitmap = null;
                    bitmap = BitmapFactory.decodeStream(in, null, null);
                    iv.setImageBitmap(bitmap);
                }catch(Exception e){
            }
        }
    

    【讨论】:

    • 我的图片尺寸过小。最大的是 351 KB
    • 这就是原因。它应该比顺利工作的更小
    【解决方案4】:

    试试 facebook 的 fresco 库。它可以处理大图像和我的一个项目,减少大约 50% 的内存消耗。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-02
      • 1970-01-01
      • 2016-01-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多