Android JetPack组成MVVM
#android #jetpackcompose #mvvm #cleanarchitecture

我将向您展示如何使用此example

使用Jetpack Componse创建屏幕视图

Jetpack Compose App

首先,让我们解释基础知识

什么是MVVM架构?

模型视图视图模型(MVVM)是行业认可的软件体系结构模式,它克服了MVP和MVC设计模式的所有缺点。 MVVM建议将数据显示逻辑(视图或UI)与应用程序的核心业务逻辑部分分开。

MVVM的单独代码层是:

  • 模型:该层是负责数据源的抽象。模型和ViewModel一起工作以获取和保存数据。
  • View :该层的目的是告知ViewModel用户的操作。该层观察ViewModel,不包含任何类型的应用程序逻辑。
  • ViewModel :它揭示了与视图相关的数据流。此外,它是模型和视图之间的链接。

什么是JetPack撰写?

JetPack组成是Android推荐的现代工具包用于构建本地UI。它简化并加速了Android上的UI开发。快速使用更少的代码,功能强大的工具和直觉的Kotlin API来使您的应用程序栩栩如生。


现在我们准备从项目开始!

*注意:在本文中,我将仅解释如何定义屏幕视图。如果您想了解更多信息,可以在GitHub上检查整个项目:JetpackComposeMVVM

Project structure

JetPack组成

要显示一个类别列表,我们首先需要定义应如何显示一个类别。在这种情况下,我们有以下(图像下图):

CategoryItem

我们还需要了解JetPack中的RowsColumns是什么:

  • 行:它水平排列视图。
  • 列:它垂直排列视图。

Row and Columns in Jetpack Compose

在这种情况下,我们有一排可以显示ImageTitleDescription。但是我们也有一个包含TitleDescription的列。

显示类别项目的代码如下:

@Composable
fun CategoryItem(category: Category, context: Context, onClickListener: (Category) -> Unit) {
    Card(
        modifier = Modifier
            .padding(8.dp, 4.dp)
            .fillMaxWidth()
            .height(300.dp)
            .clickable { onClickListener.invoke(category) },
        shape = RoundedCornerShape(25.dp),
    ) {
        Surface(
            color = Color.LightGray
        ) {

            Row(
                Modifier
                    .padding(4.dp)
                    .fillMaxSize()
            ) {

                Image(
                    painter = rememberAsyncImagePainter(
                        model = category.strThumb,
                        imageLoader = ImageLoader.Builder(context).crossfade(true).build()
                    ),
                    contentDescription = category.str,
                    modifier = Modifier
                        .fillMaxHeight()
                        .weight(0.2f)
                )
                Column(
                    verticalArrangement = Arrangement.Center,
                    modifier = Modifier
                        .padding(4.dp)
                        .fillMaxHeight()
                        .weight(0.8f)
                ) {
                    Text(
                        text = category.str,
                        style = MaterialTheme.typography.titleMedium,
                        fontWeight = FontWeight.Bold
                    )
                    Text(
                        text = category.strDescription,
                        style = MaterialTheme.typography.bodyMedium
                    )
                }
            }
        }
    }
}

一旦我们拥有一个类别的外观,我们就可以定义应如何显示列表:

@Composable
fun CategoryList(
    categoryList: List<Category>,
    context: Context,
    onClickListener: (Category) -> Unit
) {
    LazyColumn {
        itemsIndexed(items = categoryList) { _, item ->
            CategoryItem(category = item, context, onClickListener)
        }
    }
}

在这种情况下,我们定义了一个LazyColumn,这是一个垂直滚动列表,仅构成并列出当前可见的项目。它类似于经典的Android视图系统中的回收模型。

结果是:

Category List

现在,我们需要在主动脉中调用类别列表方法:

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
    private val viewModel: MainViewModel by viewModels()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MealRecipesTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    CategoryList(categoryList = viewModel.categoryList, context = this) {
                        val intent = Intent(this@MainActivity, DetailActivity::class.java).apply {
                            putExtra(DetailActivity.DETAIL_CATEGORY, it)
                        }
                        intent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP
                        startActivity(intent)
                    }
                    viewModel.getCategories()

                }
            }
        }
    }
}

请注意,当单击类别时,将显示另一种视图,其中包含所选类别的信息。这可以做到,因为在ComporyItem组合函数中我们拥有:

.clickable { onClickListener.invoke(category) }

单击类别时,我们转到另一个活动(在单击类别时,主动行为中有一个Intent)。

新活动,细节性,再次显示TitleDescriptionImage

组合功能看起来像这样:

Detail Category View

@Composable
fun CategoryItem(category: Category, context: Context) {
    Surface(
        modifier = Modifier
            .padding(4.dp)
            .fillMaxHeight(),
        color = Color.White,
    ) {
        Column(
            verticalArrangement = Arrangement.Top,
            modifier = Modifier
                .padding(20.dp)
                .fillMaxHeight()
        ) {

            Text(
                text = category.str,
                style = MaterialTheme.typography.titleMedium,
                fontWeight = FontWeight.Bold,
                modifier = Modifier
                    .padding(25.dp)
            )
            Image(
                painter = rememberAsyncImagePainter(
                    model = category.strThumb,
                    imageLoader = ImageLoader.Builder(context).crossfade(true).build()
                ),
                contentDescription = category.str,
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(top = 25.dp)
            )
            Text(
                text = category.strDescription,
                style = MaterialTheme.typography.bodyMedium,
                modifier = Modifier
                    .padding(25.dp)
            )

        }


    }
}

然后,我们需要在详细信息中调用类别函数:

@AndroidEntryPoint
class DetailActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val category = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            intent.getSerializableExtra(DETAIL_CATEGORY, Serializable::class.java) as Category
        } else {
            @Suppress("DEPRECATION")
            intent.getSerializableExtra(DETAIL_CATEGORY) as Category
        }
        setContent {
            MealRecipesTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    CategoryItem(category = category, context = this@DetailActivity)
                }
            }
        }
    }

    companion object {
        const val DETAIL_CATEGORY = "detail_category"
    }
}

结果是:

Category in detail

,仅此而已!这就是您使用JetPack Compose创建屏幕视图的方式。希望你喜欢!

如果您想在此处检查整个项目,则有链接:JetpackComposeMVVM

不要忘记喜欢和分享!谢谢! :)