在两个打开的活动之间来回移动数据
Posted
技术标签:
【中文标题】在两个打开的活动之间来回移动数据【英文标题】:Moving data back and forth between two open activities 【发布时间】:2021-11-21 12:09:03 【问题描述】:我有两个活动——act1 和 act2。我想在用户按下按钮时将字符串从 act1 传输到 act2,经过一些计算后,我想将 LatLng
从 act2 传输到 act1,同时保持两个活动打开(或者至少能够恢复 act2 中的每个更改从应用程序开始)。
我尝试过的事情:
我看到here 在使用startActivity()
时,如果我在意图中添加一些标志,我将不会开始新的活动。从 act1 到 act2 运行良好,但在从 act2 启动 act1 后,它会停止 act2,因此在下一个 act2 打开时,它将制作一个新的 act2 副本。
我查看了startActivityForResult
的未弃用版本,但由于我需要打开这两个活动,这不是我想要的。我也希望他们两个都能接收和返回数据。
来自here,在一项活动中使用静态数据结构可能不是一个好习惯。
我尝试使用 extras 和 onNewIntent
,但无法使其正常工作(因为我无法让这两个活动都运行)。
背景(如果相关):
我有一个包含两个活动的应用程序 - main,其中存储一个 ListView
和一个地图活动。
地图必须在每个保存的地址中放置一个标记。
列表有两种按钮类型:
-
“添加新地点...”,打开地图活动,并在用户想要的位置添加新标记。
-某个地址-,即在该地址对应的位置打开地图。
我需要一种将所需地址传递给地图的方法,以便它显示该位置,并且我还需要在创建位置后将新保存的地址传递回主要活动。
【问题讨论】:
【参考方案1】:您可以使用 存储库模式 以应用中所有代码都可以访问的方式存储数据。
什么是存储库?
存储库是一个简单的类,它保存一些数据并提供对它的访问。比如:
class Repository
private String theString = "";
public void setTheString(String newValue)
theString = newValue;
public String getTheString(
return theString;
为存储库提供一个更具描述性的名称是个好主意。因此,如果这是一个存储位置数据的存储库,您可以将其命名为 LocationRepository
。
应该在哪里创建?
保持对它的引用的好地方是Application
类。如果没有,可以这样定义:
class MyApplication extends Application
private Repository repository = new Repository();
public Repository getRepository()
return repository;
需要扩展android框架提供的Application
类
如果需要,您还可以覆盖 onCreate()
方法以进行更复杂的初始化
在清单中定义应用程序类
为了让 android 框架了解您的自定义 Application
类,您需要在 AndroidManifest.xml
中定义它:
<application
android:name=".MyApplication"
...
在您的活动中访问存储库
现在,您可以在每个活动中将应用程序上下文转换为您的应用程序类:
class MainActivity extends AppCompatActivity
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Repository repository = ((MyApplication) getApplicationContext()).getRepository();
System.out.println(repository.getTheString());
【讨论】:
我有几个问题: 1.我不了解Kotlin,你能解释一下onCreate的第一行(新)吗? 2.为什么我需要repository来扩展Application,如果它只存储一些数据? 3. 如何从两个活动中访问 same 存储库对象? 我将首先回答最后一个问题:使用上面的代码 (val repository = (applicationContext as MyApplication).repository
),您可以从两个活动中访问相同的存储库对象。您需要扩展 Application
以将存储库保留在其中。如果对您有更多帮助,我可以提供 Java 示例。
我希望有一个 Java 示例,同时我只使用静态列表
我将示例更改为 Java。【参考方案2】:
如果您想要一种更简洁的方法,并且您关心架构设计:
为每个活动创建一个 ViewModel 创建一个可供 ViewModel 访问的 Singleton,并使用它来共享数据。单例可能是这样的:
object AddressManager
fun saveAddress(address: Address)
fun getAddress(): Address
当然,我建议你使用 Dagger 和 Hilt 进行注入,而不是使用“对象”,但这又是越来越多的设计思路。
【讨论】:
onNewIntent 有问题吗?我认为这是他要走的路,只需要防止第二个活动停止。无论如何,我也会研究单例。顺便说一句,我正在使用 java。 您是说 onNewIntent 不起作用。不是我。其次 - 你应该区分停止和杀死。他们完全不同。我不确定究竟是什么阻止您使用 onNewIntent。关于在 Java 中创建单例 - 有很多关于它的信息。但是现代的处理方式是 ViewModel、LiveData 等。如果您在屏幕之间进行复杂的交互,主要使用 UI API - 这是不行的。 我会澄清:当我启动应用程序时,会创建 act1。我总是以标志 FLAG_ACTIVITY_SINGLE_TOP、FLAG_ACTIVITY_CLEAR_TOP 开始活动。然后我启动act2,它也在创建。现在我从act2 开始act1,它进入act1 的onNewIntent(到目前为止一切顺利)。问题是act2此时停止,当我从act1再次启动它时(它应该恢复到它),它再次创建act2 对于这种(简单)情况,使用 Dagger/Hilt 将是矫枉过正。也不需要它是一个单例。它可以是在您自己的Application
类中创建的常规对象。以上是关于在两个打开的活动之间来回移动数据的主要内容,如果未能解决你的问题,请参考以下文章