解析给ImageView设置资源的五种方法

ImageView通过setImageDrawable无效原因之多次setContentView ImageView通过setImageDrawable无效原因之一设置图片无效状态描述解决方法可能原因 设置图片无效状态描述 ImageView对象已经获取,logcat中没有显示找不到对象的错误 activity已经进行了多次setContentView 解决方法 需要多次进行setContentView时使用LayoutInflater对视图进行加载。 比如 LayoutInflate... 阅读详情

Android开发中几乎每天都要接触ImageView这个控件。这个控件可以作为加载图片的容器。ImageView给我们提供了五种设置图片资源的方法:

  • setImageBitmap(Bitmap bm)
  • setImageDrawable(Drawable drawable)
  • setImageResource(int resId)
  • setImageURI(Uri uri)
  • setImageIcon(Icon icon)

下面就通过源码来看看这5个方法的区别。

1. setImageBitmap(Bitmap bm)

setImageBitmap方法中,先把bitmap放在一个BitmapDrawable中,然后调用的setImageDrawable方法。

    public void setImageBitmap(Bitmap bm) {
        // Hacky fix to force setImageDrawable to do a full setImageDrawable
        // instead of doing an object reference comparison
        mDrawable = null;
        if (mRecycleableBitmapDrawable == null) {
            mRecycleableBitmapDrawable = new BitmapDrawable(mContext.getResources(), bm);
        } else {
            mRecycleableBitmapDrawable.setBitmap(bm);
        }
        setImageDrawable(mRecycleableBitmapDrawable);
    }
2. setImageDrawable(Drawable drawable)

setImageDrawable方法里面先调用了updateDrawable()方法,然后判断了drawable的宽高是否有改变,如果发生了改变则会调用requestLayout()方法,最后调用invalidate()方法,让新设置的drawable生效。

  • updateDrawable()
    这个方法里用于更新drawable的可见性、宽高、边界、颜色等。

  • requestLayout()
    这个方法会根据View树逐级向上传递,最后由ViewRootImpl#requestLayout方法处理该事件。ViewRootImpl#requestLayout中会调用scheduleTraversals()方法,这是一个异步方法,会调用performTraversals()方法。在performTraversals()方法中会先后调用performMeasure()和performLayout()方法。然后视条件调用performDraw()方法。

  • invalidate()
    该方法会不断向父容器请求刷新并计算需要重绘的区域,最后会传递到ViewRootImpl中触发performTraversals方法,然后调用performDraw()进行重绘。

    /**
     * Sets a drawable as the content of this ImageView.
     *
     * @param drawable the Drawable to set, or {@code null} to clear the
     *                 content
     */
    public void setImageDrawable(@Nullable Drawable drawable) {
        if (mDrawable != drawable) {
            mResource = 0;
            mUri = null;

            final int oldWidth = mDrawableWidth;
            final int oldHeight = mDrawableHeight;

            updateDrawable(drawable);

            if (oldWidth != mDrawableWidth || oldHeight != mDrawableHeight) {
                requestLayout();
            }
            invalidate();
        }
    }
3. setImageResource(int resId)

对比setImageDrawable方法的源码,发现这个方法实现里多了一个resolveUri()方法。resolveUri()通过Context#getDrawable方法完成从resource id解析出drawable对象。并且从源码注释中我们可以知道,这个方法对Bitmap的读取以及解码都是在UI线程里面完成的,所以这里面会有潜在的问题(比如当图片很大时,就有可能阻塞UI线程)。因此官方建议我们,如果担心这个问题,那么可以考虑使用setImageBitmap方法。

    /**
     * Sets a drawable as the content of this ImageView.
     *
     * <p class="note">This does Bitmap reading and decoding on the UI
     * thread, which can cause a latency hiccup.  If that's a concern,
     * consider using {@link #setImageDrawable(android.graphics.drawable.Drawable)} or
     * {@link #setImageBitmap(android.graphics.Bitmap)} and
     * {@link android.graphics.BitmapFactory} instead.</p>
     *
     * @param resId the resource identifier of the drawable
     *
     * @attr ref android.R.styleable#ImageView_src
     */
    public void setImageResource(@DrawableRes int resId) {
        // The resource configuration may have changed, so we should always
        // try to load the resource even if the resId hasn't changed.
        final int oldWidth = mDrawableWidth;
        final int oldHeight = mDrawableHeight;

        updateDrawable(null);
        mResource = resId;
        mUri = null;

        resolveUri();

        if (oldWidth != mDrawableWidth || oldHeight != mDrawableHeight) {
            requestLayout();
        }
        invalidate();
    }
4. setImageURI(Uri uri)

setImageURI和setImageResource类似,Bitmap的读取和解码都是在UI线程中,不同的是setImageUri是通过资源的Uri来获取Drawable对象。注释中提到,这个方法有一个兼容性的问题。在API<24的机器上,如果从SCHEME_CONTENT或者SCHEME_FILE的uri资源中加载图片,将无法应用正确的密度对图片进行缩放。

 /**
     * Sets the content of this ImageView to the specified Uri.
     *
     * <p class="note">This does Bitmap reading and decoding on the UI
     * thread, which can cause a latency hiccup.  If that's a concern,
     * consider using {@link #setImageDrawable(Drawable)} or
     * {@link #setImageBitmap(android.graphics.Bitmap)} and
     * {@link android.graphics.BitmapFactory} instead.</p>
     *
     * <p class="note">On devices running SDK < 24, this method will fail to
     * apply correct density scaling to images loaded from
     * {@link ContentResolver#SCHEME_CONTENT content} and
     * {@link ContentResolver#SCHEME_FILE file} schemes. Applications running
     * on devices with SDK >= 24 <strong>MUST</strong> specify the
     * {@code targetSdkVersion} in their manifest as 24 or above for density
     * scaling to be applied to images loaded from these schemes.</p>
     *
     * @param uri the Uri of an image, or {@code null} to clear the content
     */
    @android.view.RemotableViewMethod(asyncImpl="setImageURIAsync")
    public void setImageURI(@Nullable Uri uri) {
        if (mResource != 0 || (mUri != uri && (uri == null || mUri == null || !uri.equals(mUri)))) {
            updateDrawable(null);
            mResource = 0;
            mUri = uri;

            final int oldWidth = mDrawableWidth;
            final int oldHeight = mDrawableHeight;

            resolveUri();

            if (oldWidth != mDrawableWidth || oldHeight != mDrawableHeight) {
                requestLayout();
            }
            invalidate();
        }
    }
5. setImageIcon(Icon icon)

这个方法是API23中新增的方法。它会先从Icon对象中获得Drwable对象,然后调用了setImageDrawable方法。Icon是一个序列化的图形容器,里面可以包含Bitmap、压缩图片和drawable资源。Icon#loadDrawable方法也是运行在UI线程中,所以也有可能会导致UI线程阻塞。如果担心这个问题,可以用Icon#loadDrawableAsync来获取drawable对象。

    /**
     * Sets the content of this ImageView to the specified Icon.
     *
     * <p class="note">Depending on the Icon type, this may do Bitmap reading
     * and decoding on the UI thread, which can cause UI jank.  If that's a
     * concern, consider using
     * {@link Icon#loadDrawableAsync(Context, Icon.OnDrawableLoadedListener, Handler)}
     * and then {@link #setImageDrawable(android.graphics.drawable.Drawable)}
     * instead.</p>
     *
     * @param icon an Icon holding the desired image, or {@code null} to clear
     *             the content
     */
    @android.view.RemotableViewMethod(asyncImpl="setImageIconAsync")
    public void setImageIcon(@Nullable Icon icon) {
        setImageDrawable(icon == null ? null : icon.loadDrawable(mContext));
    }

总结:

  • setImageBitmap和setImageDrawable方法由于已经提供了bitmap或者drawable对象,因此不会阻塞UI线程。setImageResource、setImageURI和setImageIcon都会在UI线程中完成对Bitmap的读取和解码,因此会存在阻塞UI线程的可能。

  • setImageBitmap、setImageResource、setImageURI和setImageIcon最后都是调用setImageDrawable方法

  • setImageResource是通过Context#getDrawable(resourceId)获取drawable对象,setImageURI是通过资源的URI获取drawable对象,setImageIcon则是通过Icon#loadDrawable方法获取drawable对象。
Android UI 组件系列(三):ImageView 使用技巧与图像加载 在本篇博客中,我们详细探讨了 ImageView 作为 Android 开发中常用的 UI 组件的基本用法和一些常见的使用技巧。通过介绍 ImageView 的常用属性、如何加载网络图片、以及如何实现图片的圆角和裁剪效果,我们展示了如何充分利用 Glide 这样的强大库来优化图片加载和处理过程。 阅读详情

相关推荐

WSL 相关命令时遇到了 “无法从raw.githubusercontent.com提取分发列表、操作超时

核心问题:国内网络屏蔽raw.githubusercontent.com,导致WSL无法获取发行版列表;最优方案:优先用方案1(手动指定发行版安装),无需改配置,1分钟搞定;永久修复:用方案2(修改hosts),适合需要管理多个WSL发行版的场景;兜底方案:用方案3(手动下载安装包),适配所有网络环境。按以上步骤操作后,你不仅能正常安装WSL,等命令也能正常执行,后续可正常使用WSL搭配Docker Desktop(如切换WSL 2后端),无需再担心网络超时问题。

weixin_39766667的博客 2147

在代码中为ImageView引用图片之setImageDrawable和setBackgroundResource

在做项目的时候遇到了这个问题,虽然是一个小知识点,但还是值得记录一下。 首先说,在布局文件中Imageview用的src引用图片。想在代码中对控件的图片进行修改,于是最开始选择的是setBackgroundResource,但是发现图片是平铺的,效果并不是理想的。于是用的setImageDrawable(getResources().getDrawable()但是发现在5.1中是过期的。后面再说

张小贝的博客 3万+

C++ 程序稳定运行一段时间后异常中止?vc6 运行库的bug!!!

事件查看器提示:错误应用程序 xxxxxxx.exe,版本 0.0.0.0,错误模块 MSVCRTD.DLL,版本 6.0.9782.0,错误地址 0x00012b40。这是一个通信方面的软件,需要长期运行,在压力测试时,高负荷连续运行一定天数时必定崩溃,而且都是在msvcrtd.dll中崩溃。后来在dump文件中发现调用栈在是MSVCRTD.DLL模块,跟踪代码发现是在void * __cdecl _heap_alloc_dbg(        size_t nSize,        int nBloc

qingflying的专栏 2680

Android ImageView setImageDrawable 未生效的问题

return;

chengzhenjia的博客 1541

WinCC 7.5 读取 SQL server2016 中的表格数据

环境 win10 SQL Server 2016 WinCC V7.5 SP2 1 安装SQL Server 2016 2 选择服务器名称 .\WINCC 3 建数据库

skr? 7142

华为OD机试真题 新系统 9月27号 【数据中心最佳维护窗口】

华为OD机试真题 新系统【数据中心最佳维护窗口】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为OD机试真题 【数据中心最佳维护窗口】多语言题解。

qq_45776114的博客 1166

android setimagedrawable图片不显示,解决Android ImageView用setImageDrawable方法图片缩小的问题...

今天使用assert目录存了几张图片,然后想通过imageview显示出来,结果在一个低分辨率的手机上显示正常,但是到了一个高分辨率手机上显示图片变得非常小,看了一下apipublic voidsetAdjustViewBounds(boolean adjustViewBounds)当你需要在ImageView调整边框时保持可绘制对象的比例时,将该值设为真。参数adjustViewBoun...

weixin_42361708的博客 3056

人工智能混合编程实践:C++调用封装好的DLL进行异常检测推理

C++、Python、ONNX、人工智能、异常检测、Anomalib 2.1.0

FriendshipTang的博客 172

setImageResource和setImageDrawable区别

ImageView设置图片的方式有很多钟,可以在xml里面写android:src=”@drawable/xxx”,也可以在java代码里面设置。 在java里面的设置方式也有多种,方法包括:setImageResource,setImageDrawable,setImageBitmap。 在xml里面设置实际上和在java里面调用setImageResource是一样的,当然xml多

chenglansky的专栏 2541

Ceres&OpenCV 单目相机标定(论文复现)

Ceres&OpenCV 单目相机标定(论文复现)

dayuhaitang1的博客 371

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

在Android上设置imageview的透明背景

I am using a web view in which I am adding an image view. 我正在使用Web视图,我在其中添加图像视图。 How can I set the

xfxf996的博客 3215

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

java用url创建imageview,Android中ImageView使用网络图片资源的方法

本文实例讲述了Android中ImageView使用网络图片资源的方法。分享给大家供大家参考。具体如下:很多时候我们不想把东西都放在APK里面,或者是不能放进去,这时候我们就需要万能的网路帮助自己实现了运行效果截图如下:java代码如下:package com.android.antking.imageview;import java.io.InputStream;import java.net....

weixin_30674431的博客 672

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

ImageView设置图片的方式

一:在xml里面设置 设置前景:android:src=”@drawable/xxx” 设置背景:android:background=”@drawable/xxx” 二:在java里面的设置前景的方式 包括:setImageResource,setImageDrawable,setImageBitmap。 在xml里面设置实际上和在ja...

小老鼠的博客 842

Android ImageView如何加载网络和本地图片资源

package com.android.antking.imageview;      import java.io.InputStream;   import java.net.HttpURLConnection;   import java.net.MalformedURLException;   import java.net.URL;      import android.

susr154的博客 8031

Android修行手册-ImageView的adjustViewBounds和设置透明度

点击跳转=>爆肝万字C#基础入门大总结【建议收藏】点击跳转=>【万字】修行Android Studio技巧到出神入化,快速涨薪【建议收藏】点击跳转=>Android修行手册之从头到尾学Kotlin【全】点击跳转=>熬夜再战Android从青铜到王者-开发效率插件篇👉关于作者👉前提了解完前面ImageView的属性,再看看其他的。👉实践过程使用ImagView点出来的方法虽然有四种,但也不是随便用的:testImg.setImageAlpha(80); //兼容好,和ImageView的setAlpha

2401_84010165的博客 1052

ImageView实现原理分析

ImageView的实现涉及到构造、图片资源的加载和管理、缩放类型的设置、测量与布局逻辑以及图片的绘制。这些功能的实现确保了ImageView可以灵活地显示不同类型的图片资源,并能适应不同的布局需求。

VitorLiu的博客 1194

ImageView设置图片的几种方式

ImageView设置图片的方式有很多种 一:在xml里面设置 设置前景:android:src=”@drawable/xxx” 设置背景:android:background=”@drawable/xxx” 二:在java里面的设置前景的方式 包括:setImageResource,setImageDrawable,setIm...

u012693479的博客 7万+

ImageView中动态设置图片

关于ImageView中动态设置图片

look to the master, follow the master, 2461

ImageView使用网络图片资源

public class MainActivity extends Activity {     //定义一个图片显示控件     private ImageView imageView;     /** Called when the activity is first created. */     @Override     publi

伍新的博客 808

ImageView(图像视图)总结

ImageView(图像视图)总结

扬帆起航 1839

android imageview方法,Android ImageView 正确使用姿势

一、正确合理使用ImageView 的src 和backgroundsrc :为ImageView 原图内容,存放原图大小,不会被拉伸;background:为Imageview的背景,会根据ImageView给定的长宽进行拉伸;在ImageView中,可以同时设置src和background属性(为了减少绘制,可以根据使用场景来设置相应属性); 由于src中存放的是原图大小,如果需要对其缩放,就...

weixin_39572168的博客 603

ImageView 使用详解

极力推荐文章:欢迎收藏 Android 干货分享 阅读五分钟,每日十点,和您一起终身学习,这里是程序员Android 本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以下内容: 一、ImageView 的继承关系 二、ImageView 常用方法 三、ImageView 背景 间距属性设置 四、使用Bitmap 类型动态设置ImageView 资源 五...

anpaikan3027的博客 366

java imageview的使用_Android使用控件ImageView加载图片的方法

在 Android 加载图片一般使用 ImageView,这里简单记录一下这个控件的使用方法。最简单就是在 xml 里直接使用 ImageView 标签:android:orientation="vertical"android:layout_width="fill_parent"android:layout_height="fill_parent">android:id="@+id/iv"...

weixin_29465407的博客 848

Android ImageView 详解

目录 一、图片加载方法 二、图片缩放类型 三、updateDrawable() 原理 四、图片加载时会按缩放类型,会影响图片占用的内存大小吗? 五、总结 一、图片加载方法 在项目中,加载图片时,都会用到 ImageView,对应的几种设置图片的方式有如下几种: 在布局文件中设置属性 android:src=“@drawable/resId” 加载本地图片 setImageResource(int resId); 加载drawable文件夹中的资源文件 setImageURI(Uri);

u010194271的博客 5959
上一篇: 解决--android.view.InflateException: Binary XML file line #9: Error inflating class <unknown>
下一篇: 解决-adb pull failed remote permission denied
Huang-Lin
博客等级 码龄10年 20粉丝 58原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值