Activity 间和Fragment 间通信

围巾🧣 2024年06月24日 145次浏览

Activity 间通信

在 Android 开发中,通过 ViewModel 在 Activity 之间通信是一种优雅且推荐的方式。ViewModel 可以跨 Activity 和 Fragment 生命周期保存数据,并且可以使用 ViewModelLiveData 来实现无缝的数据共享和通信。下面是几种实现 Activity 之间通过 ViewModel 通信的优雅方法:

1. 使用 SharedViewModel

使用 SharedViewModel 是一种常见的方式,通过一个共享的 ViewModel 实例在多个 Activity 之间共享数据。SharedViewModel 通常在应用级别的 ViewModelStore 中创建,这样它可以在不同的 Activity 之间共享。

步骤:

  1. 创建一个共享的 ViewModel:

    class SharedViewModel : ViewModel() {
        val data: MutableLiveData<String> = MutableLiveData()
    }
    
  2. 在 Application 类中设置 ViewModelStore:

    class MyApplication : Application() {
        val appViewModelStore: ViewModelStore by lazy { ViewModelStore() }
    }
    
  3. 在 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 为例:

步骤:

  1. 添加 Hilt 依赖:

    dependencies {
        implementation "com.google.dagger:hilt-android:2.40.5"
        kapt "com.google.dagger:hilt-compiler:2.40.5"
    }
    
  2. 设置 Hilt:

    @HiltAndroidApp
    class MyApplication : Application()
    
  3. 创建 ViewModel:

    @HiltViewModel
    class SharedViewModel @Inject constructor() : ViewModel() {
        val data: MutableLiveData<String> = MutableLiveData()
    }
    
  4. 在 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 生命周期保存数据,并且可以使用 ViewModelLiveData 来实现无缝的数据共享和通信。下面是几种实现 Fragment 之间通过 ViewModel 通信的优雅方法:

1. 使用共享的 ViewModel

使用共享的 ViewModel 是一种常见的方式,通过一个共享的 ViewModel 实例在多个 Fragment 之间共享数据。通常,这个共享的 ViewModel 是在宿主 Activity 的作用域内创建的。

步骤:

  1. 创建一个共享的 ViewModel:

    class SharedViewModel : ViewModel() {
        val data: MutableLiveData<String> = MutableLiveData()
    }
    
  2. 在 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 做一些全局初始化的工作
        }
    }
    
  3. 在 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。这在某些场景下也非常有用。

步骤:

  1. 在发送数据的 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"))
            }
        }
    }
    
  2. 在接收数据的 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 为例:

步骤:

  1. 添加 Hilt 依赖:

    dependencies {
        implementation "com.google.dagger:hilt-android:2.40.5"
        kapt "com.google.dagger:hilt-compiler:2.40.5"
    }
    
  2. 设置 Hilt:

    @HiltAndroidApp
    class MyApplication : Application()
    
  3. 创建 ViewModel:

    @HiltViewModel
    class SharedViewModel @Inject constructor() : ViewModel() {
        val data: MutableLiveData<String> = MutableLiveData()
    }
    
  4. 在 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 之间进行通信是一种优雅且推荐的方式。无论是使用共享的 ViewModelFragmentResult API,还是依赖注入框架,都可以实现高效的数据共享和管理。选择合适的方式取决于你的具体需求和项目架构。