在两个打开的活动之间来回移动数据

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 类中创建的常规对象。

以上是关于在两个打开的活动之间来回移动数据的主要内容,如果未能解决你的问题,请参考以下文章

在视图之间来回切换时保留一个值

如何在swift中水平来回移动角色

如何使用 jquery 的 animate 方法使 div 来回移动

如何处理wifi和移动数据之间的网络变化?

c# 如何使用上下键在TextBox之间移动

如何使用 jQuery 进行拖放以在两个或多个 div 之间移动数据,然后触发对 db 的更新?