kotlin 从发生的事件组成

dzhpxtsq  于 2023-10-23  发布在  Kotlin
关注(0)|答案(2)|浏览(119)

我在这里传递的lambda是为了帮助防止重新组合titleTextLayoutResult: (hasVisualOverflow: Boolean, lineCount: Int) -> Boolean
由于这是一个LazyColumn,每次用户上下滚动时,它都会创建大量的重组。
我想是因为这个

onTextLayout = { textLayoutResult ->
    shouldShowMoreTitle =  titleTextLayoutResult(textLayoutResult.hasVisualOverflow, textLayoutResult.lineCount) 
})

我把它提取到一个lambda函数中,认为这可能会有所帮助,但它仍然是一样的。只是想知道有没有解决这个问题的办法?
我在下面添加了一些片段。但这是存储库,以防代码片段中缺少某些内容。
https://github.com/steve1rm/BusbyNews

var shouldShowMoreTitle by remember {
    mutableStateOf(false)
}

@Composable
fun NewsItem(
    modifier: Modifier = Modifier,
    articleModel: ArticleModel,
    onNewsLinkClicked: (newsLink: String) -> Unit,
    newsItemEvent: (NewsItemEvent) -> Unit,
    newsItemState: NewsItemState,
    titleTextLayoutResult: (hasVisualOverflow: Boolean, lineCount: Int) -> Boolean
) {

Text(
    modifier = Modifier
        .fillMaxWidth()
        .animateContentSize(),
    color = MaterialTheme.colorScheme.onSurface,
    style = MaterialTheme.typography.titleMedium,
    text = articleModel.title,
    maxLines =  if (showMoreTitleClicked) Int.MAX_VALUE else 1,
    overflow = TextOverflow.Ellipsis,
    onTextLayout = { textLayoutResult ->
        shouldShowMoreTitle =  titleTextLayoutResult(textLayoutResult.hasVisualOverflow, textLayoutResult.lineCount) 
    })
}

NewsItem(
    articleModel = articleModel,
    onNewsLinkClicked = onNewsLinkedClicked,
    newsItemEvent = newsItemEvent,
    newsItemState = newsItemState,
    titleTextLayoutResult = ::getTextLayoutResult)

private fun getTextLayoutResult(hasVisualOverflow: Boolean, lineCount: Int): Boolean {
    return hasVisualOverflow || lineCount > 1
}

我已经为lazy列使用了一个键,如下所示:

LazyColumn(
                modifier = Modifier.fillMaxWidth(),
                contentPadding = PaddingValues(start = 8.dp, end = 8.dp, top = 8.dp),
                verticalArrangement = Arrangement.spacedBy(6.dp),
                horizontalAlignment = Alignment.CenterHorizontally
            ) {
                items(
                    key = { articleModel ->
                        articleModel.id
                    },
                    items = newsPagingData.itemSnapshotList.items
                ) { articleModel ->
                    NewsItem(
                        articleModel = articleModel,
                        onNewsLinkClicked = onNewsLinkedClicked,
                        newsItemEvent = newsItemEvent,
                        newsItemState = newsItemState,
                        titleTextLayoutResult = ::getTextLayoutResult
                    )
                }
}

这是重组

yc0p9oo0

yc0p9oo01#

主要问题是NewsState,MainActivity中的newsItemEvent也有问题。
首先从NewsItemshouldShowProgress中删除NewState作为布尔值

@Composable
fun NewsItem(
    modifier: Modifier = Modifier,
    articleModel: ArticleModel,
    onNewsLinkClicked: (newsLink: String) -> Unit,
    newsItemEvent: (NewsItemEvent) -> Unit,
    shouldShowProgress:Boolean = false,
//    newsItemState: NewsItemState,
    titleTextLayoutResult: (hasVisualOverflow: Boolean, lineCount: Int) -> Boolean
)

然后在setContent中通过设置

val lambda = remember {
            { newsItemEvent: NewsItemEvent ->
                newsViewModel.onNewsItemEvent(newsItemEvent)

            }
        }

        val themeLambda = remember {
            { appTheme:AppTheme->
                newsApplication.toggleDarkThemeOff(appTheme)

            }
        }

打电话给新闻网

NewsScreen(
    newsPagingData = newsHeadLines,
    modifier = Modifier
        .fillMaxSize()
        .nestedScroll(connection = scrollBehavior.nestedScrollConnection),
    topAppBarScrollBehavior = scrollBehavior,
    onNewsLinkedClicked = { newsLink ->
        newsLinkState = newsLink
    },
    newsItemState = newsItemState,
    newsItemEvent = { newsItemEvent ->
//                                newsViewModel.onNewsItemEvent(newsItemEvent)
        lambda.invoke(newsItemEvent)

    },
    selectedTheme = useDarkColors,
    onSelectedTheme = { appTheme ->
//                                newsApplication.toggleDarkThemeOff(appTheme)
        themeLambda(appTheme)
    }
)

这些将消除NewsItem重组,但LazyColumn将被重组,因为NewsItemItems读取NewsState。我还在NewsItemsItems中创建了一个lambda,但这是可选的,我不认为它在任何情况下都有效。

val textLayoutResultLambda = remember {
    { hasVisualOverflow: Boolean, lineCount: Int ->
        getTextLayoutResult(hasVisualOverflow, lineCount)
    }
}

我还更新了NewState,删除了可变参数,但无论如何它仍然会触发重组。你应该关注为什么NewsState触发了不必要的重组。

@Immutable
data class NewsItemState(
    val shouldShowProgress: Boolean = false,
    val showMoreOrLessTitleText: ShowMoreOrLessTitleText = ShowMoreOrLessTitleText(),
//    val showMoreTitleClicked: Boolean = false,
    val shouldShowMoreTitle: Boolean = true,
    val shouldMoreDescriptionClicked: Boolean = false,
    val shouldShowMoreDescription: Boolean = false,
    val isDarkThemeSelected: Boolean = false
)

/** Work in-progress*/
data class ShowMoreOrLessTitleText(
    val text: String = "Show more",
    val shouldShowMoreTitle: Boolean = false,
    val hasTextOverflow: Boolean = false,
    val lineCount: Int = -1
)

fun ShowMoreOrLessTitleText.textUpdate(): String {
    return if(this.shouldShowMoreTitle)
        "Show more"
    else
        "Show less"
}

fun ShowMoreOrLessTitleText.shouldMoreText(): Boolean {
    return this.hasTextOverflow || lineCount > 1
}

在ViewModel中,您可以将其更新为

is NewsItemEvent.OnShowMoreTitleTextClicked -> {
    _newsItemState.update { newsItemState ->

        val showMoreOrLessTitleText = newsItemState.showMoreOrLessTitleText.copy(
            lineCount = newsItemEvent.showMoreOrLessTitleText.lineCount,
            hasTextOverflow = newsItemEvent.showMoreOrLessTitleText.hasTextOverflow,
            shouldShowMoreTitle =  newsItemState.showMoreOrLessTitleText.shouldMoreText(),
            text =   newsItemState.showMoreOrLessTitleText.textUpdate(),
            )

        newsItemState.copy(
            showMoreOrLessTitleText = showMoreOrLessTitleText
        )
    }
}
t2a7ltrp

t2a7ltrp2#

这样做一个rememberLazyListState

val lazyColumnListState = rememberLazyListState()

然后将它传递给LazyColumn,如下所示:

LazyColumn(
    state = lazyColumnListState,
    modifier = Modifier.fillMaxWidth(),
    contentPadding = PaddingValues(start = 8.dp, end = 8.dp, top = 8.dp),
    verticalArrangement = Arrangement.spacedBy(6.dp),
    horizontalAlignment = Alignment.CenterHorizontally
) {
    items(
        key = { articleModel ->
            articleModel.id
        },
        items = newsPagingData.itemSnapshotList.items
    ) { articleModel ->
        NewsItem(
            articleModel = articleModel,
            onNewsLinkClicked = onNewsLinkedClicked,
            newsItemEvent = newsItemEvent,
            newsItemState = newsItemState,
            titleTextLayoutResult = ::getTextLayoutResult
        )
    }
}

相关问题