附带效应

1.LaunchedEffect 

package com.tiger.jetpackcomposeside.samples

import android.annotation.SuppressLint
import android.util.Log
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Snackbar
import androidx.compose.material3.SnackbarData
import androidx.compose.material3.SnackbarDuration
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch


@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ScaffoldSample(
    scaffoldState: SnackbarHostState = SnackbarHostState()
){
    val state = remember {
        mutableStateOf(false)
    }

    val scope = rememberCoroutineScope()
    LaunchedEffect(key1 = state.value){
        scaffoldState.showSnackbar(message = "Error message", actionLabel = "Retry message", duration = SnackbarDuration.Short)
    }

    Scaffold(
        snackbarHost = {
            if (state.value&&scaffoldState.currentSnackbarData!=null){
                Log.d("ning",""+state.value)

                Snackbar(snackbarData = scaffoldState.currentSnackbarData!!)

               LaunchedEffect(Unit){
                   delay(2000)
                   state.value = false;
               }

            }
        },
        topBar = {
            TopAppBar(title = { Text(text = "脚手架示例") })
        }
    ) {

        Box(
            modifier = Modifier.fillMaxSize() ,
            contentAlignment = Alignment.Center
            ){
            Button(onClick = {
                state.value= true
            }) {
                Text(text = "Error occurs")
            }

        }

    }




}


@Composable
fun LaunchedEffectSample(){
    ScaffoldSample()


}

 2.rememberCoroutineScope

package com.tiger.jetpackcomposeside.samples

import android.annotation.SuppressLint
import android.util.DisplayMetrics
import androidx.compose.animation.core.TweenSpec
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.width
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material3.DrawerValue
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.ModalDrawerSheet
import androidx.compose.material3.ModalNavigationDrawer
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Snackbar
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.rememberDrawerState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.tiger.jetpackcomposeside.halfDp
import kotlinx.coroutines.launch


@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ScaffoldSample(){
    val snackbarHostState = SnackbarHostState()
    val scope = rememberCoroutineScope()
//不管他会不会垃圾回收,我想他应该会,因为 组件树 弹出组件外 以后 协程作用域销毁,然后有新创建回来,他又会执行一次 重组 state 对象不变,重新移除再初始化,就变了
    val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)

    ModalNavigationDrawer(
        drawerState = drawerState,
        drawerContent = {
            ModalDrawerSheet(Modifier.width(halfDp.dp)) {
                Box(modifier = Modifier.fillMaxSize(),
                    contentAlignment = Alignment.Center){
                    Text(text = "抽屉组件中的内容")
                }
            }
        },
    ) {
        Scaffold(

            snackbarHost = {
                if ( snackbarHostState.currentSnackbarData!=null){
                    Snackbar(snackbarData = snackbarHostState.currentSnackbarData!!)
                }
            },
            topBar = {
                TopAppBar(title = { Text(text = "脚手架示例") },
                    navigationIcon ={
                        IconButton(onClick = {
                            scope.launch {
                                drawerState.animateTo(DrawerValue.Open,TweenSpec())
                            }
                        }) {
                            Icon(imageVector = Icons.Filled.Menu, contentDescription = null)
                        }
                    })
            },
            floatingActionButton = {
                ExtendedFloatingActionButton(
                    content ={ Text(text = "悬浮按钮")} ,
                    onClick = {
                        scope.launch {
                            snackbarHostState.showSnackbar("点击了悬浮按钮")
                        }
                    }
                )
            }

        ) {

            Box(modifier =Modifier.fillMaxSize(),
                contentAlignment = Alignment.Center
            ){
                Text(text = "屏幕内容区域")
            }


        }

    }





}

 3.rememberUpdateState

package com.tiger.jetpackcomposeside.samples

import android.util.Log
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberUpdatedState
import kotlinx.coroutines.delay


@Composable
fun LandingScreen(func:() -> Unit) {
    val funState by rememberUpdatedState(newValue = func)
    LaunchedEffect(key1 = Unit) {
        Log.d("ning", "LaunchedEffect")
        repeat(10) {
            delay(1000)
            Log.d("ning", "delay ${it + 1}s")
        }
        funState()
    }
}


@Composable
fun RememberUpdatedStateSample() {
    val onTimeOut1: () -> Unit = { Log.d("ning", "landing timeout 1") }
    val onTimeOut2: () -> Unit = { Log.d("ning", "landing timeout 2") }

    val changeOnTimeOutState = remember {
        mutableStateOf(onTimeOut1)
    }

    Column {
        Button(onClick = {
            if (changeOnTimeOutState.value == onTimeOut1) {
                changeOnTimeOutState.value = onTimeOut2
            } else {
                changeOnTimeOutState.value = onTimeOut1
            }
        }) {
            Text(text = "choose onTimeOut")
        }
        LandingScreen(changeOnTimeOutState.value)
    }


}

 4.DisposableEffect

package com.tiger.jetpackcomposeside.samples

import android.util.Log
import androidx.activity.OnBackPressedCallback
import androidx.activity.OnBackPressedDispatcher
import androidx.compose.foundation.layout.Row
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch


@Composable
fun BackHandle(backDispatcher: OnBackPressedDispatcher, onback: () -> Unit) {


    //最后会被垃圾回收的,弹栈以后
    val backCallBack = run {
        Log.d("ning", "重新创建了对象")
        object : OnBackPressedCallback(true) {
            override fun handleOnBackPressed() {
                onback()
            }
        }
    }


    DisposableEffect(key1 = backDispatcher) {
        Log.d("ning", "当组件加入到组件树的时候执行")
        //当组件加入到组件树的时候执行
        backDispatcher.addCallback(backCallBack)


        this.onDispose {


            //被移除组件树的时候在这里面执行

            Log.d("ning", "on DisposableEffect")
            //移除组件树执行移除监听返回键操作
            backCallBack.remove()
        }
    }
}


@Composable
fun DisposableEffectSample(backDispatcher: OnBackPressedDispatcher) {

    var addBackCallback by remember {
        mutableStateOf(false)
    }

    Row {
        Switch(
            checked = addBackCallback,
            onCheckedChange = {
                addBackCallback = it
            },
            thumbContent = { Text(text = if (addBackCallback) "Add Back CallBack" else "Not Add Back CallBack") })
    }

    if (addBackCallback) {
        BackHandle(backDispatcher = backDispatcher) {
            Log.d("ning", "on back")
        }
    }


}
package com.tiger.jetpackcomposeside

import android.os.Bundle
import android.util.DisplayMetrics
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import com.tiger.jetpackcomposeside.samples.DisposableEffectSample
import com.tiger.jetpackcomposeside.samples.RememberUpdatedStateSample
import com.tiger.jetpackcomposeside.samples.ScaffoldSample1


import com.tiger.jetpackcomposeside.ui.theme.JetpackComposeSideTheme
import kotlin.math.roundToInt

var halfDp:Int =0

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            JetpackComposeSideTheme {
                val displayMetrics: DisplayMetrics = getResources().getDisplayMetrics()
                val i = displayMetrics.widthPixels / 2
                val density = displayMetrics.density
                val half = i / density.roundToInt()
                halfDp=half
                //监听
                DisposableEffectSample(this.onBackPressedDispatcher)
            }

        }
    }
}

5. SideEffect

 6. ProduceState

package com.tiger.jetpackcomposeside.samples

import android.annotation.SuppressLint
import android.util.Log
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Warning
import androidx.compose.material3.Button
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import com.tiger.jetpackcomposeside.repository.Image
import com.tiger.jetpackcomposeside.repository.ImageRepository
import com.tiger.jetpackcomposeside.repository.Result
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

@SuppressLint("ProduceStateDoesNotAssignValue")
@Composable
fun loadNetworkImage(
    url:String,
    imageRepository: ImageRepository
):State<Result<Image>>{

 return produceState(initialValue = Result.Loading as Result<Image> ,url,imageRepository){
    //启动协程的作用域其实是在主线程
     Log.d("ning","thread:${Thread.currentThread().name}")

     val image = imageRepository.load(url)

       this.value = if (image == null){
           Result.Error
       }else{
           Result.Success(image)
       }
 }
}


@Composable
fun ProduceStateSample(){

    val imagesList = remember {
        listOf<String>(
            "https://img0.baidu.com/it/u=3628503530,464378779&fm=253&app=120&size=w931&n=0&f=JPEG&fmt=auto?sec=1710522000&t=2f6a6aa742c7377edfe2e297301e6646",
            "https://img2.baidu.com/it/u=4232500544,3931871143&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1710522000&t=ee03aed4fef2ec85a23d5261e453b1d6",
            "https://img2w.baidu.com/it/u=4232500asdasdasdadq544,3931871143&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1710522000&t=ee03aed4fef2ec85a23d5261e453b1d6"
        )
    }


    var index by remember {
        mutableStateOf(0)
    }


    val imageRepository = ImageRepository(LocalContext.current)
    val result = loadNetworkImage(url = imagesList[index] , imageRepository =imageRepository )

        Column {
            Button(onClick = {
//                index %= imagesList.size
                if (++index == imagesList.size) index = 0

            }) {
                Text(text = "选择第 $index 张图片")
            }
            when(result.value){
                is  Result.Success ->{
                    Image(bitmap = (result.value as Result.Success).image.imageBitmap , contentDescription = "image load success" )
                }
                is  Result.Error ->{
                    Image(imageVector = Icons.Rounded.Warning, contentDescription = "image load error" , modifier = Modifier.size(200.dp,200.dp))
                }
                else ->{
                    CircularProgressIndicator()
                }

            }
        }





}
package com.tiger.jetpackcomposeside.repository

import android.content.Context
import android.graphics.BitmapFactory
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asImageBitmap
import com.bumptech.glide.Glide
import com.bumptech.glide.request.FutureTarget
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.withContext
import java.io.File

class ImageRepository(
    private val context: Context
) {

    suspend fun load(url: String): Image? {
        //Glide加载网络图片
        return withContext(Dispatchers.IO) {
            try {
                delay(1000)
                val future:FutureTarget<File> = Glide
                    .with(context)
                    .load(url)
                    .downloadOnly(200,200)
                val imageBitmap =
                    BitmapFactory.decodeFile(future.get().absolutePath).asImageBitmap()
                Image(imageBitmap)
            } catch (e: Exception) {
                e.printStackTrace()
                null
            }
        }
    }


}


data class Image(val imageBitmap: ImageBitmap)


sealed class Result<T>() {
    object Loading : Result<Image>()
    object Error : Result<Image>()
    data class Success(val image: Image) : Result<Image>()
}

7.derivedStateOf

 

package com.tiger.jetpackcomposeside.samples

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp

fun  String.containsWord(list: List<String>):Boolean{
    for (item in list) {
       if (this.contains(item)) return true
    }
    return false
}


@Composable
fun ItemText(text:String ,modifier: Modifier=Modifier) {
    Text(text = text, textAlign = TextAlign.Center, modifier = modifier
        .height(30.dp)
        .fillMaxSize())
}



@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TodoList(
    highPriorityWords:List<String> = listOf("review","compose","unblock")
) {
    val todoTask = remember {
        mutableStateListOf<String>()
    }

  val  highPriorityTask = remember (todoTask,highPriorityWords){
        derivedStateOf {
            todoTask.filter { it.containsWord(highPriorityWords) }
        }

  }
    var text by remember {
        mutableStateOf("")
    }
    Column {
        Row (
            verticalAlignment = Alignment.CenterVertically
        ){
            TextField(value = text, onValueChange = {
                text = it
            })
            Button(onClick = {
                todoTask.add(text)
                text = ""
            }) {
                Text(text = "Add")
            }
            
        }
        LazyColumn {
            items(highPriorityTask.value){
                ItemText(it, modifier = Modifier.background(Color.LightGray))
            }

            //所有任务
            items(todoTask){
                ItemText(it)
            }
        }
        
        
    }
}

@Composable
fun DerivedStateOfSample() {
    TodoList()
}

8.SnapshotFlow

package com.tiger.jetpackcomposeside.samples

import android.util.Log
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.snapshotFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter

@Composable
fun SnapshotFlowSample(){
    val listState = rememberLazyListState()//监听懒加载列的状态
        LazyColumn(state = listState){
            items(1000){
                Text(text = "Item $it")
            }
        }
    
    LaunchedEffect(listState){
        Log.d("ning","重新执行了")
        snapshotFlow { listState.firstVisibleItemIndex }
            .filter { it > 20}
            .distinctUntilChanged()
            .collect{
                Log.d("ning","firstVisibleItemIndex:$it")
            }
      //后面方法不会执行

    }

}

 

  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值