我想要与 TikTok 的个人资料屏幕类似的效果。顶部是ProfilPicture和username,下面是一个stickyHeader带有TabRow( Posts, Drafts, Likes, Favorites) 的 ,下面是HorizontalPager带有 4 个屏幕 ( Posts, Drafts, Likes, Favorites) 的 ,每个屏幕都包含一个列表。
如果我在 Compose 中构建它,我会崩溃,因为我无法将两个嵌套LazyColumns在一起。
这是我尝试做的事情的简短版本:
val tabList = listOf("Posts", "Drafts", "Likes", "Favorites")
val pagerState: PagerState = rememberPagerState(initialPage = 0)
val coroutineScope = rememberCoroutineScope()
LazyColumn(modifier = Modifier.fillMaxSize()) {
item {
Box(
modifier = Modifier
.fillMaxWidth()
.height(50.dp),
contentAlignment = Alignment.Center
) {
//Profile Header (Picture, …Run Code Online (Sandbox Code Playgroud) android kotlin android-jetpack-compose lazycolumn jetpack-compose-accompanist
我使用"底部导航活动"创建了一个新项目:https: //gyazo.com/f5efaecffd5adfd05e512921d3b8a19d
这是生成的代码:
package com.aaron.waller.mrpolitik;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomNavigationView;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private TextView mTextMessage;
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_home:
mTextMessage.setText(R.string.title_home);
case R.id.navigation_dashboard:
mTextMessage.setText(R.string.title_dashboard);
case R.id.navigation_notifications:
mTextMessage.setText(R.string.title_notifications);
}
return true;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextMessage = (TextView) findViewById(R.id.message);
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
}
}
Run Code Online (Sandbox Code Playgroud)
如何使用Bottom …
我的应用程序中有一个 UserStateModel(数据类)类型的 StateFlow。
private val _userStateFlow: MutableStateFlow<UserStateModel?> = MutableStateFlow(UserStateModel())
val userStateFlow: StateFlow<UserStateModel?> = _userStateFlow
Run Code Online (Sandbox Code Playgroud)
这是用户状态模型
data class UserStateModel(
val uid: String? = null,
val username: String? = null,
val profileImageUrl: String? = null,
var isLoggedIn: Boolean = false,
val isPremiumUser: Boolean = false,
val posts: List<Post>? = listOf()
)
Run Code Online (Sandbox Code Playgroud)
当我使用新的用户名更新 StateFlow 时,它会将更改发送给收集器并更新 UI。但是当我更改帖子内的属性时:列表?列表它不会发出更改。当我更改列表的大小时,它会更改,而当我更改索引 0 处的帖子的 name 属性时,它不会更改。如何检测 Data 类的子属性的更改?
现在我使用一个丑陋的解决方法,我补充道
val updateErrorWorkaround: Int = 0
Run Code Online (Sandbox Code Playgroud)
到 UserStateModel 数据类并将其加一以便收集器收到通知
PS我正在使用 MVVM + Clean Architecture 和 Jeptack Compose
编辑 这是我的帖子模型:
data class …Run Code Online (Sandbox Code Playgroud) android kotlin kotlin-coroutines android-jetpack-compose kotlin-flow
我的应用程序整体性能相当不错,唯一 FPS 下降的部分是在伴奏者滑动 HorizontalPager 时。
每个页面都有一个简单的 LazyVerticalGrid,有 3 个固定列,但与 XML 相比,性能要差得多。
LazyVerticalGrid 的外观如下:
出于测试目的,我在 XML 中开发了相同的设置,以使用 Perfetto 和 Android Studio 编译器进行比较。与 XML 相比,Jetpack Compose 版本具有更多的 Janky 框架。
这是 Perfetto 中 compose 的结果:
这里是 XML:
此外,每次我滑动 HorizontalPager 时,Profiler 都会显示一堆卡顿的帧:
我拥有 Jetpack Compose 的基本知识,并且还阅读了 Android 开发人员 Compose 性能指南,我非常确定我没有做任何导致大量重组的愚蠢事情。
这是我在测试项目中使用的代码:
可滚动 TabRow + HorizontalPager:
val tabList = listOf("Following", "Trending", "New", "Top", "Most Shared", "Most Saved", "All")
val pagerState: PagerState = rememberPagerState(initialPage = 1)
val coroutineScope = rememberCoroutineScope()
Column(
modifier = Modifier
.fillMaxSize()
.background(MaterialTheme.colors.background) …Run Code Online (Sandbox Code Playgroud) android android-jetpack android-jetpack-compose jetpack-compose-accompanist baseline-profile
我刚刚将我的源代码迁移到了 Androidx,因为我这样做了我的共享功能来共享声音不再工作。Logcat 说:
Failed to save file: /storage/emulated/0/appfolder/testsound.mp3 (Permission denied)
Run Code Online (Sandbox Code Playgroud)
这是它保存声音的部分:
final String fileName = soundObject.getItemName() + ".mp3";
File storage = Environment.getExternalStorageDirectory();
File directory = new File(storage.getAbsolutePath() + "/appfolder/");
directory.mkdirs();
final File file = new File(directory, fileName);
InputStream in = view.getContext().getResources().openRawResource(soundObject.getItemID());
try{
Log.i(LOG_TAG, "Saving sound " + soundObject.getItemName());
OutputStream out = new FileOutputStream(file);
byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer, 0, buffer.length)) != -1){
out.write(buffer, 0 , len);
}
in.close();
out.close();
} catch (IOException e){
Log.e(LOG_TAG, …Run Code Online (Sandbox Code Playgroud) 所以我目前正在关注 DigitalOcean 的本教程: https://www.digitalocean.com/community/tutorials/how-to-build-a-graphql-api-with-prisma-and-deploy-to-digitalocean-s -app-platform 我创建了一个托管在 digitalocean 上的 postgres 数据库。当我尝试使用以下命令连接到它时:
DATABASE_URL="postgresql://db:some_password@unique_identifier.db.ondigitalocean.com:25060/db?sslmode=require" npx prisma migrate deploy --preview-feature
Run Code Online (Sandbox Code Playgroud)
并将 DATABASE_URL 替换为我的个人连接字符串,它给了我以下错误:
“错误:P1001:无法访问位于 app-0336e984censored29-do-user-10651-0.b.db.ondigitalocean.com
:25060 的数据库服务器”请确保您的数据库服务器正在运行
app-0336e984censored29-do-user-10651-0.b.db.ondigitalocean.com:`25060
出了什么问题?我的数据库已上线,链接也正确
我设置了一个非常小的项目用于测试目的,并且在滑动水平页面时看到很多卡顿帧: https: //github.com/DaFaack/ComposePerformanceTest
我在启用 R8 的发布模式下构建。我究竟做错了什么?
当我记录跟踪并在 perfetto 中查看它时,它显示了很多卡顿:

使用 ViewPager + RecyclerView 在 XML 中进行相同的设置运行顺利
我尝试生成基线配置文件,但没有看到任何差异,仍然是卡顿的帧
我想知道 Jetpack Compose 是否有可能获得类似 Gmail 的行为,有人以前做过类似的事情并想分享他们的解决方案吗?
我只是想让用户有机会在上传之前向其内容添加标签,我不需要像下面的 gif 中那样的弹出建议。
只是简单的芯片InputField。

android ×7
kotlin ×4
java ×2
jetpack-compose-accompanist ×2
database ×1
graphql ×1
input-field ×1
kotlin-flow ×1
lazycolumn ×1
manifest ×1
migrate ×1
permissions ×1
postgresql ×1
share ×1