Android开发:调用类静态方法删除View时View返回null问题
你出现该问题的核心原因是:在ActivityTwo中通过LayoutInflater.inflate(R.layout.activity_main, null)得到的是全新的、未经过MainActivity动态添加子View的布局实例,和当前运行在后台的MainActivity所持有的eventsLayout完全是两个独立的对象。
你动态添加的带指定id的Event View仅存在于MainActivity的eventsLayout实例中,新inflate出来的布局里只有初始状态的空eventsLayout,自然找不到对应id的View,所以返回null。这也是为什么同样的逻辑在MainActivity中可以正常运行——MainActivity调用findViewById(R.id.eventsLayout)拿到的是自身正在展示、已经加载了所有动态子View的真实布局实例。
Android中不同Activity的View树是完全独立的,不能直接在B Activity中操作A Activity的View元素,你可以选择以下两种常用方案实现需求:
方案1:数据驱动全量刷新(逻辑最简单,推荐)
你已经有静态的Event.eventsList作为统一数据源,所有操作围绕数据源进行即可:- ActivityTwo中点击删除按钮时,首先遍历
Event.eventsList删除对应id的Event实例 - 不需要操作View,直接调用
finish()关闭ActivityTwo - 在MainActivity的
onResume()生命周期方法中执行刷新逻辑:先调用eventsLayout.removeAllViews()清空所有子View,再遍历最新的Event.eventsList重新生成对应Event View添加到eventsLayout中
该方案可以完全避免数据和视图不一致的问题,维护成本极低。
- ActivityTwo中点击删除按钮时,首先遍历
方案2:本地广播增量更新(性能更优)
如果你不想全量重绘所有View,可以用本地广播实现跨Activity轻量通信:- MainActivity中注册本地广播接收器,监听自定义的删除事件Action,收到广播时从Intent中取出要删除的id,直接调用自身
eventsLayout.findViewById(id)找到对应View删除即可 - ActivityTwo中删除对应Event实例后,发送携带删除id的本地广播,再关闭自身即可
该方案仅做增量修改,性能消耗更小。
- MainActivity中注册本地广播接收器,监听自定义的删除事件Action,收到广播时从Intent中取出要删除的id,直接调用自身
你当前用Event.eventsList.size()作为View的id存在冲突风险:如果删除过中间的Event,后续新增的Event会复用之前用过的id,可能引发逻辑异常。建议给Event类新增静态自增的idCounter属性,每次创建新Event时idCounter++作为唯一id,保证不会出现重复。
内容的提问来源于stack exchange,提问作者user13460312

