android中相近方法对比

1️⃣、getDimension() vs ``getDimensionPixelSize() vs getDimensionPixelOffset()

在 Android 开发中,getDimension()getDimensionPixelSize()getDimensionPixelOffset() 都是 Resources 类中用于获取尺寸资源的方法,主要用于将 dpsp 等单位转换为像素(px),但它们的返回值和用途有所不同:

  1. getDimension(int id)
  • 返回值float 类型,返回转换后的像素值(包含小数部分)。
  • 转换逻辑 :根据当前设备的屏幕密度,将资源中定义的 dp/sp 等单位转换为精确的像素值(可能带有小数)。
  • 适用场景:需要精确像素值(如动画中的细微位置计算、绘制自定义 View 时的坐标定位等)。
java 复制代码
// 示例:获取 res/values/dimens.xml 中定义的尺寸
float dimension = getResources().getDimension(R.dimen.margin);
  1. getDimensionPixelSize(int id)
  • 返回值int 类型,返回转换后四舍五入的像素值(整数)。
  • 转换逻辑 :先执行与 getDimension() 相同的转换,得到 float 像素值,再通过四舍五入(Math.round())取整。
  • 适用场景 :大多数 UI 布局场景(如设置 View 的宽高、边距等),因为 View 的尺寸属性(layout_width 等)只接受整数像素。
java 复制代码
int pixelSize = getResources().getDimensionPixelSize(R.dimen.button_height);
view.setHeight(pixelSize); // View 高度需整数像素
  1. getDimensionPixelOffset(int id)
  • 返回值int 类型,返回转换后截断小数的像素值(整数,相当于 (int)floatValue)。

  • 转换逻辑 :先执行与 getDimension() 相同的转换,得到 float 像素值,再直接截断小数部分(取整数部分,不四舍五入)。

  • 适用场景:需要严格向下取整的场景(如避免因四舍五入导致的布局溢出)。

    int pixelOffset = getResources().getDimensionPixelOffset(R.dimen.padding);
    view.setPadding(pixelOffset, 0, 0, 0);

对比总结

方法 返回类型 转换方式 典型用途
getDimension() float 精确转换(保留小数) 动画、绘制等需要高精度的场景
getDimensionPixelSize() int 四舍五入取整 大多数 UI 布局(宽高、边距等)
getDimensionPixelOffset() int 截断小数取整 需严格向下取整的布局场景

注意事项

  • 这三个方法的输入都是尺寸资源 ID(定义在 res/values/dimens.xml 中,单位可以是 dpsppx 等)。
  • 对于 px 单位的资源,三者返回值一致(因为无需转换,直接返回整数或浮点形式的像素值)。
  • 推荐优先使用 getDimensionPixelSize() 处理 UI 布局,它的四舍五入逻辑更符合人眼对尺寸的感知。

在 Android 开发中,除了 getDimension()getDimensionPixelSize()getDimensionPixelOffset(),还有其他获取尺寸资源的方法,适用于不同场景

  1. getFraction()
  • 功能:获取资源中定义的分数值,可根据参考尺寸计算实际像素。

  • 适用场景:需按比例计算尺寸时,比如根据父容器大小设置子 View 尺寸。

  • 使用示例

    xml

    XML 复制代码
    <!-- 在 res/values/dimens.xml 中定义 -->
    <fraction name="half_width">50%p</fraction> <!-- 相对于父容器的50% -->

    使用

    java 复制代码
    // 参数:资源ID、基准宽度、基准高度(单位px),返回计算后的float值
    float halfWidth = getResources().getFraction(R.fraction.half_width, parentWidth, parentHeight);
  1. getInteger()
  • 功能:获取资源中定义的整数类型尺寸或数值。

  • 适用场景:获取整数配置,如网格列数、最大显示数量等。

  • 使用示例

    xml

    XML 复制代码
    <!-- 在 res/values/integers.xml 中定义 -->
    <integer name="grid_columns">3</integer>

    使用

    java 复制代码
    int columns = getResources().getInteger(R.integer.grid_columns);
  1. getDimensionForSize()(API 29+)
  • 功能 :专为获取 View 尺寸设计,返回值为 int,效果类似 getDimensionPixelSize()

  • 特点:在 API 29 及以上版本中,推荐用于 View 尺寸设置,更符合布局场景。

  • 使用示例

    java 复制代码
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        int size = getResources().getDimensionForSize(R.dimen.view_size);
        view.setLayoutParams(new ViewGroup.LayoutParams(size, size));
    }
  1. TypedValue 配合 resolveDimension()
  • 功能:手动解析尺寸资源,获取原始值和单位,适合需要自定义转换逻辑的场景。

  • 使用示例

    java 复制代码
    TypedValue typedValue = new TypedValue();
    getResources().getValue(R.dimen.margin, typedValue, true);
    // 获取原始值和单位(如 typedValue.data 为值,typedValue.unit 为单位)
    float value = typedValue.getDimension(getResources().getDisplayMetrics());
  1. 直接从 TypedArray 中获取
  • 功能 :在自定义 View 的 obtainStyledAttributes() 中获取布局文件中定义的尺寸属性。

  • 适用场景:自定义 View 解析自定义属性时使用。

  • 使用示例

    java 复制代码
    TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyCustomView);
    // 类似 getDimensionPixelSize()
    int customSize = ta.getDimensionPixelSize(R.styleable.MyCustomView_customSize, 0);
    ta.recycle();

总结

这些方法适用场景各有不同:

  • 比例计算用 getFraction()
  • 整数配置用 getInteger()
  • 高版本 View 尺寸设置用 getDimensionForSize()
  • 自定义解析逻辑用 TypedValue
  • 自定义 View 属性解析用 TypedArray 相关方法。

2️⃣、View 测量与布局相关的临近方法

这些方法用于 View 的尺寸计算和位置确定,常配套使用:

方法 功能 关联方法 区别与联系
measure(int widthMeasureSpec, int heightMeasureSpec) 测量 View 所需尺寸 getMeasuredWidth() getMeasuredHeight() measure() 触发测量,后两者获取测量结果(测量尺寸)
layout(int l, int t, int r, int b) 确定 View 在父容器中的位置 getLeft()/getTop() getRight()/getBottom() layout() 确定位置,后四者获取相对父容器的坐标
onMeasure(int, int) onLayout(boolean, int, int, int, int) 自定义 View 时重写的测量和布局逻辑 setMeasuredDimension() 前者需调用 setMeasuredDimension() 保存测量结果,后者用于子 View 布局
getWidth() getHeight() 获取 View 最终显示的宽高 getMeasuredWidth() getMeasuredHeight() 前者是布局后实际尺寸,后者是测量尺寸,多数情况相等,但存在测量≠布局的场景(如父容器强制限制)

3️⃣、资源获取相关的临近方法

用于获取各类资源,因返回值或用途不同而区分:

方法 功能 关联方法 区别与联系
getResources().getString(int id) 获取字符串资源 getString(int id, Object... formatArgs) 后者支持格式化(如 %s 占位符替换)
getDrawable(int id) 获取 Drawable 资源 getDrawable(int id, Theme theme) 后者可指定主题(API 21+),适配不同主题下的资源
getColor(int id) 获取颜色值 getColor(int id, Theme theme) 类似 Drawable,后者支持主题(API 23+)
getDimension(...) 系列 获取尺寸资源(见前文) getFraction(...) getInteger(...) 同属资源获取,但处理不同类型(尺寸、分数、整数)

4️⃣、Intent 跳转相关的临近方法

用于 Activity 跳转和数据传递,功能互补:

方法 功能 关联方法 区别与联系
startActivity(Intent) 启动新 Activity startActivityForResult(Intent, int) 后者期望从新 Activity 获取返回数据(已被 Activity Result API 替代)
startService(Intent) 启动服务 bindService(Intent, ServiceConnection, int) 前者启动独立服务,后者绑定服务并获取交互接口
putExtra(String, ...) 向 Intent 中添加数据 getExtra(String) 前者存数据,后者取数据,配套用于组件间通信

5️⃣、SharedPreferences 操作相关的临近方法

用于轻量级数据存储,读写逻辑对应:

方法 功能 关联方法 区别与联系
edit() 获取编辑器对象 commit() apply() edit() 开启编辑,后两者提交修改(commit() 同步返回结果,apply() 异步高效)
getString(String, String) 获取 String 类型数据 putString(String, String) 读写对应,其他类型(int/boolean 等)也有类似成对方法

6️⃣、线程与 Handler 相关的临近方法

用于线程间通信,控制任务执行时机:

方法 功能 关联方法 区别与联系
post(Runnable) 向 Handler 所在线程(通常主线程)提交任务 postDelayed(Runnable, long) 后者延迟执行任务,均用于切换到主线程更新 UI
sendMessage(Message) 发送消息到消息队列 handleMessage(Message) 前者发消息,后者在 Handler 中处理消息,是消息机制的核心配对方法
runOnUiThread(Runnable) 在主线程执行任务 post(Runnable)(Handler) 两者功能类似,runOnUiThread 是 Activity 的便捷方法,内部依赖 Handler

分析临近方法的意义

  1. 避免误用 :例如区分 getMeasuredWidth()getWidth(),避免在 onMeasure() 中使用 getWidth()(此时布局未完成,值为 0)。
  2. 理解设计逻辑 :如 commit()apply() 的区别,体现了 Android 对性能(异步)和可靠性(同步返回结果)的平衡。
  3. 优化代码 :例如用 apply() 替代 commit() 提升 SharedPreferences 写入性能,用 Activity Result API 替代过时的 startActivityForResult()

7️⃣、startActivityForResult() vs Activity Result API

功能 :均用于从启动的 Activity 获取返回数据
区别

维度 startActivityForResult()(已过时) Activity Result API(推荐)
用法 重写 onActivityResult() 处理返回数据 注册 ActivityResultCallback 回调
生命周期关联 依赖 Activity 生命周期,易因配置变化丢失数据 与生命周期解耦,自动处理配置变化
类型安全 需手动解析数据,易出错 支持泛型,编译期检查类型
示例代码 startActivityForResult(intent, REQUEST_CODE); @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { ... } ActivityResultLauncher launcher = registerForActivityResult(...); launcher.launch(intent);<br>

8️⃣、commit() vs apply()(SharedPreferences)

功能 :提交 SharedPreferences 的编辑内容
区别

维度 commit() apply()(推荐)
执行方式 同步执行,阻塞当前线程 异步执行,提交到主线程队列
返回值 boolean,表示提交是否成功 无返回值
适用场景 需要知道提交结果的场景(极少) 大多数场景,性能更优
注意事项 主线程调用可能导致 ANR 不会阻塞线程,但数据未持久化时进程被杀会丢失

9️⃣、getWidth() vs getMeasuredWidth()

功能 :获取 View 的宽度
区别

维度 getWidth() getMeasuredWidth()
时机 布局(layout())完成后有效 测量(measure())完成后有效
数值来源 实际显示宽度(right - left 测量得出的宽度(setMeasuredDimension() 设置)
典型场景 布局完成后获取最终尺寸 自定义 View 测量阶段获取测量结果
特殊情况 可能被父容器强制修改(如超出父布局) 反映 View 自身期望的尺寸

🔟、invalidate() vs postInvalidate()

功能 :触发 View 重绘
区别

维度 invalidate() postInvalidate()
调用线程 必须在主线程调用 可在子线程调用
实现原理 直接触发重绘流程 内部通过 Handler 切换到主线程调用 invalidate()
适用场景 主线程中更新 UI 后重绘 子线程中计算数据后触发重绘

🔟1️⃣、dp vs sp vs px

功能 :定义尺寸单位
区别

维度 dp(density-independent pixel) sp(scale-independent pixel) px(pixel)
适配性 随屏幕密度变化,保证不同设备显示比例一致 除屏幕密度外,还受系统字体大小影响 固定像素,不适配
适用场景 布局尺寸(宽高、边距等) 文字大小 极少使用(如精确像素绘制)

🔟2️⃣、View.setVisibility(View.GONE) vs View.setVisibility(View.INVISIBLE)

功能 :控制 View 的可见性
区别

维度 GONE INVISIBLE
空间占用 不占用布局空间,相当于从布局中移除 占用空间,但完全透明
测量与布局 不参与测量和布局流程 参与测量和布局,只是不绘制
适用场景 临时隐藏且需释放空间 临时隐藏但保持布局结构

🔟3️⃣、getString() vs getText()

功能 :获取字符串资源
区别

维度 getString(int resId) getText(int resId)
返回类型 String CharSequence
支持资源类型 纯文本字符串 支持带样式的字符串(如 <b> 标签)
示例 getString(R.string.app_name) getText(R.string.styled_text)

总结

相似方法的核心区别通常体现在:

  • 线程安全性 (如 invalidate() 主线程 vs postInvalidate() 子线程)
  • 生命周期关联(如旧版启动 vs Activity Result API)
  • 性能与副作用 (如 commit() 同步 vs apply() 异步)
  • 适用场景 (如 dp 用于布局 vs sp 用于文字)

使用时需根据具体场景(线程、生命周期、性能需求等)选择,优先使用官方推荐的新 API(如 Activity Result API 替代 startActivityForResult())。

🔟4️⃣、其他

案例 1:finish() vs onBackPressed()(Activity 关闭相关)

相似点 :都可用于关闭当前 Activity
差异分析

  • finish():直接触发 Activity 销毁流程,调用后 Activity 进入 onDestroy() 生命周期,适合在代码逻辑中主动关闭页面(如点击 "完成" 按钮)。

    java 复制代码
    // 点击按钮关闭页面
    btnFinish.setOnClickListener(v -> finish());
  • onBackPressed():是系统回调方法,当用户按下物理返回键或导航栏返回按钮时触发。默认实现是调用 finish(),但可重写以添加额外逻辑(如双击返回退出、弹窗确认)。

    java 复制代码
    @Override
    public void onBackPressed() {
        // 自定义逻辑:如果是首页,双击返回退出
        if (isHomePage && System.currentTimeMillis() - lastBackTime < 2000) {
            super.onBackPressed(); // 调用父类实现(即 finish())
        } else {
            Toast.makeText(this, "再按一次退出", Toast.LENGTH_SHORT).show();
            lastBackTime = System.currentTimeMillis();
        }
    }

选择依据 :主动关闭用 finish();拦截返回键行为用 onBackPressed()

案例 2:setVisibility(View.GONE) vs removeView()(View 移除相关)

相似点 :都可让 View 从界面消失
差异分析

  • setVisibility(View.GONE):View 仍存在于布局结构中,只是不显示且不占用空间,可通过 setVisibility(View.VISIBLE) 恢复显示,适合临时隐藏(如切换列表筛选状态)。

    java 复制代码
    // 筛选条件不满足时隐藏按钮
    btnFilter.setVisibility(filterCondition ? View.VISIBLE : View.GONE);
  • removeView():将 View 从父容器中彻底移除,若需再次显示需重新调用 addView() 添加,适合确定不再使用的场景(如动态表单删除某一行)。

    java 复制代码
    // 从父布局中移除不需要的输入项
    parentLayout.removeView(extraInputView);

选择依据 :临时隐藏且可能恢复用 GONE;永久移除用 removeView()

案例 3:notifyDataSetChanged() vs notifyItemChanged(int)(RecyclerView 刷新相关)

相似点 :都用于刷新 RecyclerView 列表
差异分析

  • notifyDataSetChanged():通知列表 "所有数据已变",会触发整个列表重新绑定和绘制,效率低,适合数据批量替换或结构变化(如切换数据源)。

    java 复制代码
    // 整体数据替换时使用
    mList = newData;
    adapter.notifyDataSetChanged();
  • notifyItemChanged(int position):仅通知指定位置的数据变化,只会重新绑定该位置的 Item,效率高,适合单个数据更新(如点赞状态变化)。

    java 复制代码
    // 仅更新第5项数据
    mList.get(5).setLiked(true);
    adapter.notifyItemChanged(5);

选择依据 :局部更新用 notifyItemXXX 系列方法;全量刷新才用 notifyDataSetChanged()

案例 4:postDelayed(Runnable, long) vs Handler.postDelayed(Runnable, long)(延迟任务相关)

相似点 :都可实现延迟执行任务
差异分析

  • View.postDelayed(Runnable, long):任务在 View 所在的线程(通常是主线程)执行,且会检查 View 是否已被销毁(mAttachInfo != null),避免内存泄漏,适合与 View 相关的延迟操作(如延迟隐藏提示框)。

    java 复制代码
    // 延迟3秒隐藏提示框
    tipView.postDelayed(() -> tipView.setVisibility(View.GONE), 3000);
  • Handler.postDelayed(Runnable, long):需要手动管理 Handler 的生命周期,若 Handler 持有 Activity 引用且未及时移除任务,可能导致内存泄漏,适合全局延迟任务(如定时轮询)。

    java 复制代码
    // 需在 Activity 销毁时调用 handler.removeCallbacksAndMessages(null)
    Handler handler = new Handler(Looper.getMainLooper());
    handler.postDelayed(() -> doPolling(), 5000);

选择依据 :与 View 相关的延迟任务用 View.postDelayed();全局任务用 Handler 并注意及时取消。

案例 5:getStringArray() vs getResources().obtainTypedArray()(数组资源获取相关)

相似点 :都用于获取资源文件中定义的数组
差异分析

  • getStringArray(int resId):直接获取字符串数组,适合简单的字符串数组(如 string-array 定义的列表项)。

    XML 复制代码
    <!-- res/values/arrays.xml -->
    <string-array name="city_list">
        <item>北京</item>
        <item>上海</item>
    </string-array>

    使用

    java 复制代码
    String[] cities = getResources().getStringArray(R.array.city_list);
  • obtainTypedArray(int resId):获取 typed-array 资源,支持多种类型(字符串、图片、尺寸等),适合复杂数组(如图文混排的列表)。

    XML 复制代码
    <!-- res/values/arrays.xml -->
    <typed-array name="icon_text_array">
        <item>@drawable/ic_home</item>
        <item>首页</item>
        <item>@drawable/ic_profile</item>
        <item>我的</item>
    </typed-array>

    运行

    java 复制代码
    TypedArray ta = getResources().obtainTypedArray(R.array.icon_text_array);
    Drawable homeIcon = ta.getDrawable(0);
    String homeText = ta.getString(1);
    ta.recycle(); // 必须回收,避免内存泄漏

选择依据 :纯字符串数组用 getStringArray();多类型数组用 typed-array 配合 obtainTypedArray()

相关推荐
这儿有一堆花2 小时前
eSIM技术深度解析:从物理芯片到数字革命
android·ios
雨白5 小时前
开发 SunnyWeather:Android 天气预报 App(下)
android
_extraordinary_6 小时前
Java 字符串常量池 +反射,枚举和lambda表达式
android·java·开发语言
alexhilton6 小时前
学会说不!让你彻底学会Kotlin Flow的取消机制
android·kotlin·android jetpack
来来走走6 小时前
Flutter dart运算符
android·前端·flutter
青小莫7 小时前
IDM下载失败常见原因
android
阿华的代码王国7 小时前
【Android】日期选择器
android·xml·java·前端·后端
小墙程序员9 小时前
Android 性能优化(五)Heap Dump 的使用
android·性能优化