避免静态视图引用,但启用不同的活动来修改视图
Posted
技术标签:
【中文标题】避免静态视图引用,但启用不同的活动来修改视图【英文标题】:avoiding static view references but enabling a different activity to modify the views 【发布时间】:2019-09-26 16:53:32 【问题描述】:我正在使用 UsbSerial (com.github.felHR85:UsbSerial:4.5) 将串行数据从虚拟串行端口(通过 USB)流式传输到我的应用程序。 MainActivity
有一个处理程序,用于处理来自 USB 服务的消息,类似于提供的示例:
https://github.com/felHR85/UsbSerial/blob/master/example/src/main/java/com/felhr/serialportexample/MainActivity.java
我的应用程序有几个活动,如果某些数据通过串行端口,其中许多活动的视图应该会改变。例如,TextView
可能需要更新显示的文本,Button
应启用或禁用。
为了在每个活动中操作onCreate
方法之外的视图,我尝试过的最简单的方法是将视图声明为private static
,但我在很多地方都看到这是一种不好的做法。我将视图引用设置回 null,如此处所述(在“2.静态视图”下),我认为,以避免潜在的内存泄漏:https://blog.nimbledroid.com/2016/09/06/stop-memory-leaks.html
我仍然不喜欢 android Studio 中的 Lint 指示“不要将 Android 上下文类放在静态字段中”这一事实。而且这种做法似乎普遍不受欢迎。
每个活动都有一个public static boolean isActive
,在onResume
中设置true
,在onPause
中设置false
来自MainActivity
的处理程序根据当前正在运行的活动(例如SecondActivity.isActive==true
)决定如何处理传入的串行数据。然后它从当前正在运行的活动(例如SecondActivity.updateViews(serialdata)
)中调用public static
方法,该活动可以访问静态视图引用以执行它需要的操作(例如myTextView.setText(serialdata)
)
如果我不应该保留对视图的静态引用,有什么替代方法可以实现我所需要的,即从MainActivity
中的处理程序更新SecondActivity
中的视图元素,而SecondActivity
是已经运行了吗?
【问题讨论】:
Activity 可以在您离开后立即被杀死,因此在暂停后运行处理程序是违反生命周期的。转到开发者选项并启用“不保留活动” - 这会模拟内存不足的环境,在这种环境中,所有活动都会在您离开后立即被终止。 【参考方案1】:MainActivity 有一个处理程序,用于处理来自 USB 服务的消息
这不是一个好计划。
我的应用程序有几个活动,如果某些数据通过串行端口,其中许多活动的视图应该会改变。
这说明了为什么不好的计划不好。来自串行端口的数据并非专门绑定到MainActivity
...那么为什么MainActivity
会处理USB 服务消息?
(也很可能您不应该在这里有多个活动,而是有一个包含多个片段的活动,但我暂时将其放在一边)
什么是实现我需要的替代方法
我不知道串行端口的另一端是什么导致消息被发送。出于这个答案的目的,我将其称为“事物”。
步骤#1:创建ThingyRepository
。这将是一个管理 USB 串行连接并接收消息的类(带有一个单例实例)。它将根据过去的消息 (ThingyState
) 保留当前状态的某种表示,并在新消息进入时更新该状态。
第 2 步:让 ThingyRepository
公开某种“反应式 API”。这可能是现代的东西,例如LiveData
或 RxJava。它可能是更老的东西,比如基于回调的 API。无论哪种方式,您都希望ThingyRepository
在状态更改时将更新的ThingyState
对象传递给相关方(“观察者”)。因此,ThingyRepository
将 USB 串行消息转换为更新的状态,并根据需要发出这些状态。
第 3 步:让您的 UI 观察 ThingyRepository
,接收 ThingyState
对象,并根据这些状态更新 UI。理想情况下,您将使用ViewModel
来调解这些通信,以处理Android 的配置更改(屏幕旋转等)。但是,如果您想保持“老派”,该活动可以使用您的ThingyRepository
注册回调,其中ThingyRepository
可以使用新的ThingyState
调用回调,因为数据会根据 USB 消息发生变化。
现在,您已将状态更改与任何单个活动分离。每个活动都可以负责根据新状态确定自己的 UI 中需要更改的内容。而且,您不再需要静态视图。
【讨论】:
其他一些注意事项:我需要支持Android 6.0。该应用程序并非旨在作为通用用途,而是用于仅限于运行该应用程序的特定手机。它不会旋转视图。 @yorisimo:这些都不会改变我的答案。 抱歉,我在完成之前点击了提交的评论。首先,我要感谢 LiveData/ViewModel 的建议。这需要Android 8.0吗?如果是这样,我将遵循“老派”的建议 @yorisimo:“这需要 Android 8.0 吗?” -- 不,它们肯定可以在 Android 6.0 上运行,甚至更早。 我发现关于 ViewModel、LiveData 和 Room 的 Smartherd youtube 教程对理解这些概念很有帮助。以上是关于避免静态视图引用,但启用不同的活动来修改视图的主要内容,如果未能解决你的问题,请参考以下文章