Kotlin数据流 - - -SharedFlow


SharedFlow,此数据流会向从其中收集值的所有使用方发出数据,及类似于广播的一对多通信。

一.导入依赖:

implementation "androidx.activity:activity-ktx:1.1.0"
implementation "androidx.fragment:fragment-ktx:1.2.5"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.2'

二.创建SharedFlow

object LocalEventBus  {
    val events= MutableSharedFlow< Event>()
    suspend fun  postEvent(event: Event){
        events.emit(event)  //发送数据
    }
}

data class Event(val timestamp:Long)

此类就定义了一个SharedFlow,并发送了数据。

三.定义SharedViewModel

class SharedViewModel :ViewModel() {
        private lateinit var job: Job
    fun startRefresh(){
        //开启协程 
        job=viewModelScope.launch (Dispatchers.IO){
            while (true){  //发送数据
                LocalEventBus.postEvent(Event(System.currentTimeMillis()))
            }
        }
    }
    fun stopRefresh(){
        job.cancel()  //关闭协程
    }
}

在ViewModel类里就开启了协程并发送了数据。

四.创建子fragment并展示数据

class TextsFragment : Fragment() {

    private val mBinding : FragmentTextsHOWBinding by lazy {
        FragmentTextsHOWBinding.inflate(layoutInflater)
    }


    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return mBinding.root
    }

    override fun onStart() {
        super.onStart()
        lifecycleScope.launchWhenCreated {
            LocalEventBus.events.collect {
                mBinding.tvShow.text=" ${it.timestamp}"
            }
        }
    }
}

在子Fragment里接收数据。

五.在主XML文件里引用子fragment

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

    </data>

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".fragment.SharedFragment">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <fragment
                android:id="@+id/one"
                android:name="com.example.flowpractice.fragment.TextsFragment"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1" />

            <fragment
                android:id="@+id/two"
                android:name="com.example.flowpractice.fragment.TextsFragment"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1" />

            <fragment
                android:id="@+id/three"
                android:name="com.example.flowpractice.fragment.TextsFragment"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1" />

        </LinearLayout>

        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:id="@+id/btn_start"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|start"
            android:layout_marginLeft="8dp"
            android:layout_marginBottom="8dp"
            android:src="@drawable/ic_start" />

        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:id="@+id/btn_stop"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:layout_marginRight="8dp"
            android:layout_marginBottom="8dp"
            android:src="@drawable/ic_stop" />

    </FrameLayout>
</layout>

在主XML文件里引入子Fragment。

六.在主fragment里控制开始与关闭

class SharedFragment : Fragment() {
        private val viewModel by viewModels<SharedViewModel>()

    private val mBinding  :FragmentSharedFlowBinding by lazy {
        FragmentSharedFlowBinding.inflate(layoutInflater)
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return mBinding.root
    }


    override fun onStart() {
        super.onStart()
            mBinding.apply {
                btnStart.setOnClickListener {
                    viewModel.startRefresh() //开启协程
                }
                btnStop.setOnClickListener {
                    viewModel.stopRefresh()  //关闭协程
                }
            }
    }
}

演示效果:


版权声明:本文为m0_47914176原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。