【问题标题】: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. “添加新地点...”,打开地图活动,并在用户想要的位置添加新标记。
  2. -某个地址-,即在该地址对应的位置打开地图。

我需要一种将所需地址传递给地图的方法,以便它显示该位置,并且我还需要在创建位置后将新保存的地址传递回主要活动。

【问题讨论】:

    标签: android google-maps android-intent android-activity


    【解决方案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 类中创建的常规对象。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-29
    • 1970-01-01
    • 1970-01-01
    • 2012-06-08
    • 1970-01-01
    • 1970-01-01
    • 2013-10-13
    相关资源
    最近更新 更多