Activity 间通信
在 Android 开发中,通过 ViewModel
在 Activity 之间通信是一种优雅且推荐的方式。ViewModel
可以跨 Activity 和 Fragment 生命周期保存数据,并且可以使用 ViewModel
和 LiveData
来实现无缝的数据共享和通信。下面是几种实现 Activity 之间通过 ViewModel
通信的优雅方法:
1. 使用 SharedViewModel
使用 SharedViewModel
是一种常见的方式,通过一个共享的 ViewModel
实例在多个 Activity 之间共享数据。SharedViewModel
通常在应用级别的 ViewModelStore
中创建,这样它可以在不同的 Activity 之间共享。
步骤:
-
创建一个共享的 ViewModel:
class SharedViewModel : ViewModel() { val data: MutableLiveData<String> = MutableLiveData() }
-
在 Application 类中设置 ViewModelStore:
class MyApplication : Application() { val appViewModelStore: ViewModelStore by lazy { ViewModelStore() } }
-
在 Activity 中获取 SharedViewModel:
class FirstActivity : AppCompatActivity() { private val sharedViewModel: SharedViewModel by viewModels({ (application as MyApplication).appViewModelStore }) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_first) // 设置数据 sharedViewModel.data.value = "Hello from FirstActivity" } } class SecondActivity : AppCompatActivity() { private val sharedViewModel: SharedViewModel by viewModels({ (application as MyApplication).appViewModelStore }) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_second) // 观察数据 sharedViewModel.data.observe(this, Observer { data -> // 更新 UI findViewById<TextView>(R.id.textView).text = data }) } }
2. 使用依赖注入框架(Hilt)
使用依赖注入框架如 Dagger 或 Hilt,可以简化 ViewModel
的共享和管理。这里以 Hilt 为例:
步骤:
-
添加 Hilt 依赖:
dependencies { implementation "com.google.dagger:hilt-android:2.40.5" kapt "com.google.dagger:hilt-compiler:2.40.5" }
-
设置 Hilt:
@HiltAndroidApp class MyApplication : Application()
-
创建 ViewModel:
@HiltViewModel class SharedViewModel @Inject constructor() : ViewModel() { val data: MutableLiveData<String> = MutableLiveData() }
-
在 Activity 中注入 ViewModel:
@AndroidEntryPoint class FirstActivity : AppCompatActivity() { private val sharedViewModel: SharedViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_first) // 设置数据 sharedViewModel.data.value = "Hello from FirstActivity" } } @AndroidEntryPoint class SecondActivity : AppCompatActivity() { private val sharedViewModel: SharedViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_second) // 观察数据 sharedViewModel.data.observe(this, Observer { data -> // 更新 UI findViewById<TextView>(R.id.textView).text = data }) } }
Fragment 间通信
在 Android 开发中,通过 ViewModel
在 Fragment 之间通信是一种优雅且推荐的方式。ViewModel
可以跨 Fragment 生命周期保存数据,并且可以使用 ViewModel
和 LiveData
来实现无缝的数据共享和通信。下面是几种实现 Fragment 之间通过 ViewModel
通信的优雅方法:
1. 使用共享的 ViewModel
使用共享的 ViewModel
是一种常见的方式,通过一个共享的 ViewModel
实例在多个 Fragment 之间共享数据。通常,这个共享的 ViewModel
是在宿主 Activity 的作用域内创建的。
步骤:
-
创建一个共享的 ViewModel:
class SharedViewModel : ViewModel() { val data: MutableLiveData<String> = MutableLiveData() }
-
在 Activity 中获取 SharedViewModel 并共享给 Fragment:
class HostActivity : AppCompatActivity() { private val sharedViewModel: SharedViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_host) // 这里你可以用 ViewModel 做一些全局初始化的工作 } }
-
在 Fragment 中获取 SharedViewModel:
class FirstFragment : Fragment() { private val sharedViewModel: SharedViewModel by activityViewModels() override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { return inflater.inflate(R.layout.fragment_first, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // 设置数据 sharedViewModel.data.value = "Hello from FirstFragment" } } class SecondFragment : Fragment() { private val sharedViewModel: SharedViewModel by activityViewModels() override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { return inflater.inflate(R.layout.fragment_second, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // 观察数据 sharedViewModel.data.observe(viewLifecycleOwner, Observer { data -> // 更新 UI view.findViewById<TextView>(R.id.textView).text = data }) } }
2. 使用 FragmentResult
API
FragmentResult
API 是 AndroidX 提供的一种新的通信方式,允许 Fragment 之间传递数据,而无需依赖宿主 Activity 或 ViewModel。这在某些场景下也非常有用。
步骤:
-
在发送数据的 Fragment 中设置结果:
class FirstFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { return inflater.inflate(R.layout.fragment_first, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // 设置结果 view.findViewById<Button>(R.id.sendButton).setOnClickListener { setFragmentResult("requestKey", bundleOf("dataKey" to "Hello from FirstFragment")) } } }
-
在接收数据的 Fragment 中接收结果:
class SecondFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { return inflater.inflate(R.layout.fragment_second, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // 接收结果 parentFragmentManager.setFragmentResultListener("requestKey", this) { _, bundle -> val result = bundle.getString("dataKey") view.findViewById<TextView>(R.id.textView).text = result } } }
3. 使用依赖注入框架(Hilt)
使用依赖注入框架如 Dagger 或 Hilt,可以简化 ViewModel
的共享和管理。这里以 Hilt 为例:
步骤:
-
添加 Hilt 依赖:
dependencies { implementation "com.google.dagger:hilt-android:2.40.5" kapt "com.google.dagger:hilt-compiler:2.40.5" }
-
设置 Hilt:
@HiltAndroidApp class MyApplication : Application()
-
创建 ViewModel:
@HiltViewModel class SharedViewModel @Inject constructor() : ViewModel() { val data: MutableLiveData<String> = MutableLiveData() }
-
在 Activity 和 Fragment 中注入 ViewModel:
@AndroidEntryPoint class HostActivity : AppCompatActivity() { private val sharedViewModel: SharedViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_host) } } @AndroidEntryPoint class FirstFragment : Fragment() { private val sharedViewModel: SharedViewModel by activityViewModels() override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { return inflater.inflate(R.layout.fragment_first, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) sharedViewModel.data.value = "Hello from FirstFragment" } } @AndroidEntryPoint class SecondFragment : Fragment() { private val sharedViewModel: SharedViewModel by activityViewModels() override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { return inflater.inflate(R.layout.fragment_second, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) sharedViewModel.data.observe(viewLifecycleOwner, Observer { data -> view.findViewById<TextView>(R.id.textView).text = data }) } }
通过 ViewModel
在 Fragment 之间进行通信是一种优雅且推荐的方式。无论是使用共享的 ViewModel
、FragmentResult
API,还是依赖注入框架,都可以实现高效的数据共享和管理。选择合适的方式取决于你的具体需求和项目架构。