在Compose中控制组件中数据的流速

文章目录

  • 一、场景描述
  • 二、代码示例
    • 1、第一种写法, 使用MutableSharedFlow进行控制
    • 第二种写法:使用MutableIntState或者MutableStateFlow进行控制
    • 第三种写法,最简洁的写法
  • 三、参考链接

一、场景描述

在Compose中设计思想是分为状态和组件的,组件由状态控制。这个操作和传统的AndroidView不太一样。在Compose中对话框Dialog也是一个组件,其显示和隐藏由外部状态控制。这里有一个场景,假设显示和关闭的时间间隔过短的话,需要将时间延长至两秒后再隐藏。针对这种问题有两种写法,一种是外部控制显示隐藏时机,一种是内部控制。外部控制较为简单,这里不再记录。本文记录下内部控制方式。

二、代码示例

1、第一种写法, 使用MutableSharedFlow进行控制

这种写法由外部传入一个flow来进行控制

class HomePage{
	private val countFlow = MutableSharedFlow<String>()
	@Composable
	fun FlowWidget(text: String){
	    val (state,change) = remember {
	        mutableStateOf("323123")
	    }
	    LaunchedEffect(text){
	        countFlow.emit(text)
	    }
	    LaunchedEffect(Unit) {
	        countFlow.buffer().collect{
	            delay(2000)
	            change(it)
	            Log.e("YM--->","接受值-->${it}--->time:${System.currentTimeMillis()}")
	        }
	    }
	    Text(text = state)
	}
}

测试代码如下:

@RequiresApi(Build.VERSION_CODES.O)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val flowContent = mutableStateOf("1")
        lifecycleScope.launch(Dispatchers.IO) {
            delay(1000)
            flowContent.value = "2"
            delay(1000)
            flowContent.value = "3"
        }
        setContent {
            ComposeTestTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colors.background
                ) {
                    Box(modifier = Modifier.size(100.dp, 100.dp)) {
                        FlowWidget(flowContent.value)
                    }
                }
            }
        }
    }

第二种写法:使用MutableIntState或者MutableStateFlow进行控制

这种写法的话里面类型需要传递MutableIntState类型,不能是Int类型。因为这个变量的实例对象需要和内部的flow中引用的实例保持同一个对象才行。MutableIntState类型也可以换成MutableStateFlow,这样里面就不用转换成flow了,但是需要转换成state进行数据接收,参考链接:Compose State的各种转换

Box(modifier = Modifier.size(100.dp, 100.dp)) {
	val count = remember {
    	mutableIntStateOf(1)
      }
    FlowWidget(count){
       count.intValue = count.intValue + 1
    }
}


@Composable
fun FlowWidget(intValue: MutableIntState, click: () -> Unit){
    Log.e("YM---->","---->接收的参数:${intValue}")
    Column {
        val (newCount, newChange) = remember {
            mutableIntStateOf(1)
        }
        LaunchedEffect(Unit){
            snapshotFlow { intValue.intValue }
                .buffer()
                .collect {
                    Log.e("YM--->","收集的参数:${it}")
                    delay(1000)
                    newChange(it)
                }
        }
        Button(onClick = click) {
            Text(text = "点击增加数值")
        }
        Text(text = "新增的值:${newCount}", fontSize = 16.sp,)
    }
}

第三种写法,最简洁的写法

Box(modifier = Modifier.size(100.dp, 100.dp)) {
	val count = remember {
    	mutableIntStateOf(1)
      }
    FlowWidget(count.intValue){
       count.intValue = count.intValue + 1
    }
}

@Composable
fun FlowWidget(innerIntValue: Int, click: () -> Unit){
    Log.e("YM---->","---->接收的参数:${innerIntValue}")
    val intState = rememberUpdatedState(newValue = innerIntValue) 
//    以下写法为rememberUpdatedState的源码写法,采用了remember的key值不变里面数据只会初始化一次的原理
//    val intState = remember {
//        mutableIntStateOf(innerIntValue)
//    }.apply { intValue = innerIntValue }

    Column {
        val (newCount, newChange) = remember {
            mutableIntStateOf(1)
        }
        LaunchedEffect(Unit){
            snapshotFlow { intState.value }
                .buffer()
                .collect {
                    Log.e("YM--->","收集的参数:${it}")
                    delay(1000)
                    newChange(it)
                }
        }
        Button(onClick = click) {
            Text(text = "点击增加数值")
        }
        Text(text = "新增的值:${newCount}", fontSize = 16.sp,)
    }
}

三、参考链接

  1. Compose State的各种转换

你可能感兴趣的:(JetPack,android)