如何通过一个Activity修改另一Activity中TextView的字号
现有实现的核心问题
你当前的写法存在三个明确的不规范问题:
- 直接通过
MainActivity的静态公开变量持有Activity实例,会造成严重内存泄漏,Activity销毁后静态引用仍持有实例会导致GC无法回收内存,极易触发OOM崩溃 - 跨Activity直接操作另一个页面的View,完全违反Android组件生命周期设计:当MainActivity被系统回收重建、处于后台不可见状态时,直接操作其View会触发空指针、状态错乱等不可预期问题
- 大量重复的
findViewById和setTextSize调用,代码冗余度极高,后续新增控件时需要重复修改代码,维护成本很高
规范实现方案
Android跨页面传值的标准实现是使用页面结果返回机制,将用户输入的字号值回传给MainActivity,由MainActivity在自身生命周期内更新View,完全不需要持有其他Activity的实例。
第一步:修改SecondActivity逻辑
点击按钮时仅做输入校验和结果回传,直接关闭当前页即可,禁止直接操作MainActivity的任何View:
buttonChangeFontSizeOfCalculator.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String inputContent = editTextInsertSize.getText().toString().trim(); // 输入合法性校验,避免非法输入触发崩溃 if (inputContent.isEmpty()) { editTextInsertSize.setError("请输入字号数值"); return; } float fontSize; try { fontSize = Float.parseFloat(inputContent); } catch (NumberFormatException e) { editTextInsertSize.setError("请输入合法数字"); return; } // 将字号塞入返回Intent Intent resultIntent = new Intent(); resultIntent.putExtra("key_font_size", fontSize); setResult(RESULT_OK, resultIntent); // 关闭当前页回到MainActivity finish(); } });
第二步:修改MainActivity逻辑
首先删除MainActivity中公开的静态mainActivity实例,这个静态变量是造成问题的核心根源。
使用AndroidX提供的Activity Result API监听SecondActivity的返回结果,拿到字号后递归遍历页面根布局下的所有TextView,批量设置字号,不需要逐个编写findViewById代码:
// 在MainActivity中注册页面返回回调 ActivityResultLauncher<Intent> fontSizeSettingLauncher = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), result -> { if (result.getResultCode() == RESULT_OK && result.getData() != null) { float targetFontSize = result.getData().getFloatExtra("key_font_size", 14f); // 传入页面根布局,批量更新所有TextView字号 ViewGroup pageRoot = findViewById(R.id.main_root_layout); applyFontSizeToAllTextViews(pageRoot, targetFontSize); } } ); // 跳转SecondActivity时使用注册好的launcher启动,替换原有startActivity调用 // 示例:findViewById(R.id.to_setting_btn).setOnClickListener(v -> { // fontSizeSettingLauncher.launch(new Intent(MainActivity.this, SecondActivity.class)); // }); // 递归遍历布局,给所有TextView设置字号的工具方法 private void applyFontSizeToAllTextViews(View currentView, float fontSize) { if (currentView instanceof TextView) { ((TextView) currentView).setTextSize(fontSize); } else if (currentView instanceof ViewGroup) { ViewGroup viewGroup = (ViewGroup) currentView; for (int i = 0; i < viewGroup.getChildCount(); i++) { applyFontSizeToAllTextViews(viewGroup.getChildAt(i), fontSize); } } }
可选优化
- 如果需要字号设置在App重启后仍然生效,可以将字号值存储到
SharedPreferences中,MainActivity在onCreate生命周期中读取存储值,调用同样的遍历方法设置字号即可 - 递归遍历设置字号的逻辑会自动覆盖后续新增的所有TextView,不需要因为页面新增控件修改设置字号的代码
- 所有用户输入的内容必须增加合法性校验,避免空值、非数字输入触发
NumberFormatException崩溃
注意:绝对不要通过静态变量持有Activity、View等Context相关对象,这是Android开发中的典型错误写法,除内存泄漏外,当Activity因屏幕旋转、系统内存不足被重建时,静态变量持有的是已销毁的旧Activity实例,操作其上的View必然触发崩溃。
内容的提问来源于stack exchange,提问作者m0ntr3
相关产品推荐
相关产品推荐

