Pol*_*ion 0 android kotlin retrofit2 android-jetpack-compose
MainActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = Screen.LoginScreen.route
) {
composable(route = Screen.LoginScreen.route) {
navBackStackEntry ->
val factory = HiltViewModelFactory(LocalContext.current, navBackStackEntry)
val viewModel: LoginViewModel = viewModel(key = "LoginViewModel", factory = factory)
LoginScreen(
viewModel = viewModel,
onNavigateToNextScreen = navController::navigate,
navController = navController
)
}
composable(route = Screen.HomeScreen.route) {
navBackStackEntry ->
val factory = HiltViewModelFactory(LocalContext.current, navBackStackEntry)
val viewModel: HomeViewModel = viewModel(key = "HomeViewModel", factory = factory)
HomeScreen(
)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
屏幕.kt
sealed class Screen (
val route: String,
){
object LoginScreen: Screen("loginScreen")
object HomeScreen: Screen("homeScreen")
}
Run Code Online (Sandbox Code Playgroud)
登录屏幕.kt
@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun LoginScreen(
viewModel: LoginViewModel,
onNavigateToNextScreen: (String) -> Unit,
navController: NavController
) {
val focusManager = LocalFocusManager.current
val keyboardController = LocalSoftwareKeyboardController.current
val empno = viewModel.empno.value
val password = viewModel.password.value
val loading = viewModel.loading.value
val user = viewModel.user.value
val dialogQueue = viewModel.dialogQueue
var isPasswordVisible by remember {
mutableStateOf(false)
}
val isFormValid by derivedStateOf {
empno.isNotBlank() && password.isNotBlank()
}
Scaffold(backgroundColor = Color.White) {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Top
) {
if (loading && user == null) {
LoadingRecipeShimmer(imageHeight = IMAGE_HEIGHT.dp)
}
else if (!loading && user != null) {
//Something to do.
val route = Screen.HomeScreen.route
onNavigateToNextScreen(route)
}else {
Spacer(modifier = Modifier.height(16.dp))
Image(
painter = painterResource(id = R.drawable.image_login),
contentDescription = "loginImage",
modifier = Modifier
.weight(1f)
.size(300.dp)
)
Card(
modifier = Modifier
.weight(2f)
.padding(8.dp),
shape = RoundedCornerShape(32.dp)
) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(32.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(
text = "CompanyApp",
fontWeight = FontWeight.Bold,
fontSize = 40.sp
)
Column(
Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.weight(1f))
OutlinedTextField(
value = empno,
onValueChange = {
viewModel.setEmpno(it)
},
modifier = Modifier
.fillMaxWidth(),
label = { Text(text = "EmployeeNumber") },
singleLine = true,
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Number,
imeAction = ImeAction.Next
),
keyboardActions = KeyboardActions(
onNext = {
focusManager.moveFocus(FocusDirection.Down)
}
),
trailingIcon = {
if (empno.isNotBlank()) {
IconButton(
onClick = {
viewModel.setEmpno("")
}) {
Icon(
imageVector = Icons.Filled.Clear,
contentDescription = "")
}
}
}
)
Spacer(modifier = Modifier.height(16.dp))
OutlinedTextField(
value = password,
onValueChange = {
viewModel.setPassword(it)
},
modifier = Modifier
.fillMaxWidth(),
label = { Text(text = "Password") },
singleLine = true,
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.NumberPassword,
imeAction = ImeAction.Done
),
keyboardActions = KeyboardActions(
onDone = {
keyboardController?.hide()
viewModel.login()
}
),
visualTransformation = if (isPasswordVisible) VisualTransformation.None else PasswordVisualTransformation(),
trailingIcon = {
IconButton(onClick = { isPasswordVisible = !isPasswordVisible }) {
Icon(
imageVector = if (isPasswordVisible) Icons.Default.Visibility else Icons.Default.VisibilityOff,
contentDescription = "Password Toggle"
)
}
}
)
Spacer(modifier = Modifier.height(16.dp))
Button(
onClick = {
keyboardController?.hide()
viewModel.login()
},
enabled = isFormValid,
modifier = Modifier
.fillMaxWidth()
.height(60.dp),
shape = RoundedCornerShape(16.dp)
) {
Text(text = "Login")
}
Spacer(modifier = Modifier.weight(1f))
}
}
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
LoginViewModel.kt
@HiltViewModel
class LoginViewModel @Inject constructor(
private val login: Login,
private val connectivityManager: ConnectivityManager,
private val state: SavedStateHandle
) : ViewModel() {
val empno = mutableStateOf("")
val password = mutableStateOf("")
val user: MutableState<User?> = mutableStateOf(null)
val loading = mutableStateOf(false)
val onLoad: MutableState<Boolean> = mutableStateOf(false)
val dialogQueue = DialogQueue()
fun setEmpno(empno: String) {
this.empno.value = empno
}
fun setPassword(password: String) {
this.password.value = password
}
init {
}
fun login() {
val auth = Auth(store_code = "2001", empno = empno.value, password = password.value)
login.execute(auth).onEach { dataState ->
loading.value = dataState.loading
dataState.data?.let { data ->
user.value = data
}
dataState.error?.let { error ->
Log.e(TAG, "getRecipe: ${error}")
dialogQueue.appendErrorMessage("An Error Occurred", error)
}
}.launchIn(viewModelScope)
}
}
Run Code Online (Sandbox Code Playgroud)
主屏幕.kt
@Composable
fun HomeScreen(
) {
Card(
modifier = Modifier.fillMaxSize()
) {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(
text = "HomeScreen",
fontWeight = FontWeight.Bold,
fontSize = 40.sp
)
}
}
}
Run Code Online (Sandbox Code Playgroud)
按登录按钮尝试登录并接收用户信息,它会转到下一个屏幕。(主屏幕)但是,当登录并转到下一个主屏幕时,屏幕闪烁并输出以下消息。
Background concurrent copying GC freed 821063(20MB) AllocSpace objects, 4(1176KB) LOS objects, 49% free, 19MB/38MB, paused 77us total 100.203ms
2021-11-01 11:51:04.493 32596-4299/com.woorimart.projectapp I/rt.woorimartap: Background concurrent copying GC freed 783275(19MB) AllocSpace objects, 3(960KB) LOS objects, 49% free, 21MB/43MB, paused 42us total 107.347ms
2021-11-01 11:51:12.030 32596-4299/com.woorimart.projectapp I/rt.woorimartap: Background concurrent copying GC freed 905429(22MB) AllocSpace objects, 3(768KB) LOS objects, 49% free, 23MB/46MB, paused 43us total 112.243ms
2021-11-01 11:51:15.313 32596-4299/com.woorimart.projectapp I/rt.woorimartap: Background concurrent copying GC freed 951843(23MB) AllocSpace objects, 3(1184KB) LOS objects, 48% free, 25MB/49MB, paused 38us total 114.812ms
2021-11-01 11:51:22.273 32596-4299/com.woorimart.projectapp I/rt.woorimartap: Background concurrent copying GC freed 1030020(25MB) AllocSpace objects, 2(872KB) LOS objects, 47% free, 26MB/50MB, paused 45us total 101.114ms
2021-11-01 11:51:36.202 32596-4299/com.woorimart.projectapp I/rt.woorimartap: Background concurrent copying GC freed 1035054(25MB) AllocSpace objects, 2(1008KB) LOS objects, 44% free, 30MB/54MB, paused 42us total 126.748ms
2021-11-01 11:51:38.349 32596-4299/com.woorimart.projectapp I/rt.woorimartap: Background concurrent copying GC freed 903031(22MB) AllocSpace objects, 3(3596KB) LOS objects, 41% free, 33MB/57MB, paused 40us total 127.925ms
2021-11-01 11:51:41.070 32596-4299/com.woorimart.projectapp I/rt.woorimartap: Background concurrent copying GC freed 975005(24MB) AllocSpace objects, 3(1584KB) LOS objects, 40% free, 35MB/59MB, paused 46us total 106.787ms
Run Code Online (Sandbox Code Playgroud)
网上查了一下,发现是gson不匹配,但是当我打印Log.d中的值时,却正常打印了该值。如果在进入下一个屏幕之前我需要添加任何内容,请告诉我。
编辑。我做了一些实验。当我将HomeScreen的代码放入LoginScreen并更改屏幕时,不会发生冻结现象。
像这样,
...
else if (!loading && user != null) {
//Something to do.
//navController.navigate(Screen.HomeScreen.route)
Card(
modifier = Modifier.fillMaxSize()
) {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(
text = "HomeScreen",
fontWeight = FontWeight.Bold,
fontSize = 40.sp
)
}
}
}else {
...
Run Code Online (Sandbox Code Playgroud)
Main Activity 的代码似乎有问题,但我猜不出问题所在。如果您知道,请告诉我。
该日志相对正常,可能与闪存无关。Java 和 Kotlin 都是垃圾收集语言。系统会每隔一段时间就决定释放不再使用的内存。在 Activity 之间切换是常见的情况,因为您突然需要新对象(尤其是新视图层次结构)的内存,并且如果前一个 Activity 正在完成,则可能可以释放其中的大部分内存。这些消息只是告诉您 GC 运行及其状态。
因此,如果您看到问题,它可能与这些日志无关。
如果您只是出于好奇想要进一步细分,
Background concurrent copying GC freed 783275(19MB) AllocSpace objects, 3(960KB) LOS objects, 49% free, 21MB/43MB, paused 42us total 107.347ms
Run Code Online (Sandbox Code Playgroud)
并发复制GC是Android从8开始使用的GC形式。在此之前它使用较旧的标记和清除算法。
它释放了 783275 个对象,占用了 19 MB 的空间。这实际上是一个巨大的数字,让我很好奇为什么会有这么多的存在。它释放了大对象空间(用于大对象的内存池)中的 3 个对象。完成后,您的堆空闲了 49%(43 MB 中的 21 MB)。该操作花费了 107 毫秒,并且您的应用程序需要暂停 42 微秒,同时移动一些数据。
除了大量的物体之外,这一切都是相当标准的。对象的数量可能也不重要,现代编程技术使用很多小对象。
| 归档时间: |
|
| 查看次数: |
4129 次 |
| 最近记录: |