You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android开发:两个Activity间双向数据传递并维持活动状态的实现方案问询

解决方案:结合ViewModel与Activity启动标记实现双Activity存活+双向传值

针对你的需求——两个Activity(主ListView页面、地图页面)同时存活,互相传递数据且保留页面状态,我推荐以下方案,完美规避你之前遇到的各种问题:

核心思路

  1. 保留Activity实例:使用FLAG_ACTIVITY_REORDER_TO_FRONT启动Activity,无论从哪个页面跳转,都会把已存在的目标Activity实例调到前台,不会销毁旧实例也不会新建,确保两个Activity同时存活,地图页面的标记等状态也能完整保留。
  2. 安全共享数据:用Jetpack的ViewModel(基于Application上下文的共享实例)实现跨Activity数据传递,替代静态变量(避免内存泄漏)和Intent extras(无法实时通知),同时利用LiveData实现数据变化的自动通知。

具体实现步骤

1. 添加ViewModel依赖

在你的app模块build.gradle(或build.gradle.kts)中添加ViewModel依赖:

dependencies {
    // Kotlin用户
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2"
    // Java用户
    implementation "androidx.lifecycle:lifecycle-viewmodel:2.6.2"
}

2. 创建共享ViewModel

这个ViewModel会作为两个Activity之间的数据中转站,用MutableLiveData包装需要传递的数据:

Kotlin版本

import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MutableLiveData
import com.google.android.gms.maps.model.LatLng

class SharedLocationViewModel(application: Application) : AndroidViewModel(application) {
    // 主Activity传递给地图Activity的目标地址
    val targetAddress = MutableLiveData<String?>()
    // 地图Activity返回给主Activity的新位置
    val newLocation = MutableLiveData<LatLng?>()
}

Java版本

import android.app.Application;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.MutableLiveData;
import com.google.android.gms.maps.model.LatLng;

public class SharedLocationViewModel extends AndroidViewModel {
    private final MutableLiveData<String> targetAddress = new MutableLiveData<>();
    private final MutableLiveData<LatLng> newLocation = new MutableLiveData<>();

    public SharedLocationViewModel(Application application) {
        super(application);
    }

    public MutableLiveData<String> getTargetAddress() {
        return targetAddress;
    }

    public MutableLiveData<LatLng> getNewLocation() {
        return newLocation;
    }
}

3. 主Activity(act1)实现

主Activity负责设置目标地址、观察地图返回的新位置,并用指定标记启动地图Activity:

Kotlin版本

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.content.Intent
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.observe
import com.google.android.gms.maps.model.LatLng
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {
    private lateinit var sharedViewModel: SharedLocationViewModel
    // 假设这是你的地址数据源
    private val yourAddressList = mutableListOf("北京市天安门", "上海市外滩")

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 获取基于Application的共享ViewModel实例
        sharedViewModel = ViewModelProvider(
            this,
            ViewModelProvider.AndroidViewModelFactory.getInstance(application)
        ).get(SharedLocationViewModel::class.java)

        // 监听地图返回的新位置,更新ListView
        sharedViewModel.newLocation.observe(this) { latLng ->
            latLng?.let {
                // 这里可以根据LatLng逆地理编码获取地址,添加到数据源
                val newAddress = getAddressFromLatLng(it)
                yourAddressList.add(newAddress)
                // 刷新ListView(假设你的Adapter叫addressAdapter)
                addressAdapter.notifyDataSetChanged()
                // 重置LiveData,避免重复处理
                sharedViewModel.newLocation.value = null
            }
        }

        // "添加新地点..."按钮点击事件
        btn_add_location.setOnClickListener {
            val intent = Intent(this, MapActivity::class.java)
            intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
            startActivity(intent)
        }

        // ListView中地址项的点击事件(示例)
        list_view.setOnItemClickListener { _, _, position, _ ->
            val selectedAddress = yourAddressList[position]
            // 将地址设置到ViewModel
            sharedViewModel.targetAddress.value = selectedAddress
            // 启动地图Activity
            val intent = Intent(this, MapActivity::class.java)
            intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
            startActivity(intent)
        }
    }

    // 示例:根据LatLng获取地址(需要实现地理编码逻辑)
    private fun getAddressFromLatLng(latLng: LatLng): String {
        // 这里可以用Geocoder或网络API实现逆地理编码
        return "新添加的地点"
    }
}

Java版本

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.content.Intent;
import android.widget.Button;
import android.widget.ListView;
import androidx.lifecycle.ViewModelProvider;
import com.google.android.gms.maps.model.LatLng;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    private SharedLocationViewModel sharedViewModel;
    private List<String> yourAddressList = new ArrayList<>();
    // 假设你的Adapter实例
    private AddressAdapter addressAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 初始化地址数据源
        yourAddressList.add("北京市天安门");
        yourAddressList.add("上海市外滩");
        addressAdapter = new AddressAdapter(this, yourAddressList);

        // 获取共享ViewModel实例
        sharedViewModel = new ViewModelProvider(
                this,
                ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication())
        ).get(SharedLocationViewModel.class);

        // 监听地图返回的新位置
        sharedViewModel.getNewLocation().observe(this, latLng -> {
            if (latLng != null) {
                String newAddress = getAddressFromLatLng(latLng);
                yourAddressList.add(newAddress);
                addressAdapter.notifyDataSetChanged();
                // 重置LiveData
                sharedViewModel.getNewLocation().setValue(null);
            }
        });

        // "添加新地点..."按钮
        Button btnAddLocation = findViewById(R.id.btn_add_location);
        btnAddLocation.setOnClickListener(v -> {
            Intent intent = new Intent(MainActivity.this, MapActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
            startActivity(intent);
        });

        // ListView点击事件
        ListView listView = findViewById(R.id.list_view);
        listView.setAdapter(addressAdapter);
        listView.setOnItemClickListener((parent, view, position, id) -> {
            String selectedAddress = yourAddressList.get(position);
            sharedViewModel.getTargetAddress().setValue(selectedAddress);
            Intent intent = new Intent(MainActivity.this, MapActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
            startActivity(intent);
        });
    }

    private String getAddressFromLatLng(LatLng latLng) {
        // 实现逆地理编码逻辑
        return "新添加的地点";
    }
}

4. 地图Activity(act2)实现

地图Activity负责监听目标地址、定位到对应位置,以及将新位置返回给主Activity:

Kotlin版本

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.content.Intent
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.observe
import com.google.android.gms.maps.CameraUpdateFactory
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.OnMapReadyCallback
import com.google.android.gms.maps.SupportMapFragment
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.MarkerOptions
import java.util.*

class MapActivity : AppCompatActivity(), OnMapReadyCallback {
    private lateinit var sharedViewModel: SharedLocationViewModel
    private lateinit var map: GoogleMap

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_map)

        // 获取共享ViewModel
        sharedViewModel = ViewModelProvider(
            this,
            ViewModelProvider.AndroidViewModelFactory.getInstance(application)
        ).get(SharedLocationViewModel::class.java)

        // 初始化地图
        val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
        mapFragment.getMapAsync(this)
    }

    override fun onMapReady(googleMap: GoogleMap) {
        map = googleMap

        // 监听主Activity传递的目标地址,定位到对应位置
        sharedViewModel.targetAddress.observe(this) { address ->
            address?.let {
                geocodeAndMoveCamera(it)
                // 重置LiveData
                sharedViewModel.targetAddress.value = null
            }
        }

        // 长按地图添加标记,并返回新位置给主Activity
        map.setOnMapLongClickListener { latLng ->
            map.addMarker(MarkerOptions().position(latLng))
            // 将新位置设置到ViewModel
            sharedViewModel.newLocation.value = latLng
            // 返回主Activity
            val intent = Intent(this, MainActivity::class.java)
            intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
            startActivity(intent)
        }
    }

    // 根据地址获取LatLng并移动地图相机
    private fun geocodeAndMoveCamera(address: String) {
        val geocoder = android.location.Geocoder(this, Locale.getDefault())
        try {
            val addresses = geocoder.getFromLocationName(address, 1)
            if (!addresses.isNullOrEmpty()) {
                val location = addresses[0]
                val latLng = LatLng(location.latitude, location.longitude)
                map.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 15f))
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
}

Java版本

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.content.Intent;
import androidx.lifecycle.ViewModelProvider;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import java.util.List;
import java.util.Locale;

public class MapActivity extends AppCompatActivity implements OnMapReadyCallback {
    private SharedLocationViewModel sharedViewModel;
    private GoogleMap map;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_map);

        // 获取共享ViewModel
        sharedViewModel = new ViewModelProvider(
                this,
                ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication())
        ).get(SharedLocationViewModel.class);

        // 初始化地图
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        map = googleMap;

        // 监听目标地址,定位到对应位置
        sharedViewModel.getTargetAddress().observe(this, address -> {
            if (address != null) {
                geocodeAndMoveCamera(address);
                sharedViewModel.getTargetAddress().setValue(null);
            }
        });

        // 长按地图添加标记并返回主Activity
        map.setOnMapLongClickListener(latLng -> {
            map.addMarker(new MarkerOptions().position(latLng));
            sharedViewModel.getNewLocation().setValue(latLng);
            Intent intent = new Intent(MapActivity.this, MainActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
            startActivity(intent);
        });
    }

    private void geocodeAndMoveCamera(String address) {
        android.location.Geocoder geocoder = new android.location.Geocoder(this, Locale.getDefault());
        try {
            List<android.location.Address> addresses = geocoder.getFromLocationName(address, 1);
            if (addresses != null && !addresses.isEmpty()) {
                android.location.Address location = addresses.get(0);
                LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
                map.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 15f));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

方案优势

  1. Activity状态完整保留:FLAG_ACTIVITY_REORDER_TO_FRONT确保两个Activity实例始终存活,地图页面的标记、缩放状态等不会丢失,完全符合你的需求。
  2. 安全的跨组件传值:ViewModel由Application上下文管理,避免了静态变量的内存泄漏问题,且生命周期与应用进程绑定,即使Activity重建(如屏幕旋转)数据也不会丢失。
  3. 实时数据通知:LiveData的观察机制让数据变化时自动触发UI更新,无需手动处理Intent传递的时机问题。

注意事项

  • 地理编码部分:Geocoder在部分设备或离线场景下可能失效,建议结合网络地理编码API做降级处理。
  • 如果需要管理更复杂的状态(如多个标记的集合),可以在ViewModel中用MutableLiveData<List<LatLng>>来维护,实现地图页面标记的持久化。

内容的提问来源于stack exchange,提问作者benjamin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 14:42:42