我需要使用导航,并且我还需要在每个屏幕中使用SharedViewModel. 这是我尝试过的。
class MainActivity : ComponentActivity() {
private lateinit var navController: NavHostController
private val viewModel: SharedViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
navController = rememberNavController()
NavGraph(
navController = navController,
sharedViewModel = sharedViewModel
)
}
}
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,我将navController和传递sharedViewModel 给了NavGraph。
fun NavGraph(
navController: NavHostController,
sharedViewModel: SharedViewModel
) {
NavHost(
navController = navController,
startDestination = HomeScreen.route
) {
composable(
route = HomeScreen.route
) {
HomeScreen(
sharedViewModel = sharedViewModel
)
}
composable(
route …Run Code Online (Sandbox Code Playgroud) android kotlin android-jetpack-navigation android-jetpack-compose dagger-hilt
我需要在 MVVM 中获取用户身份验证状态。在存储库中我这样做:
override fun getAuthResponse() = callbackFlow {
val listener = AuthStateListener {
Log.d(TAG, "currentUser: " + (currentUser == null)) //Line2
trySend(it.currentUser == null)
}
auth.addAuthStateListener(listener)
awaitClose {
auth.removeAuthStateListener(listener)
}
}
Run Code Online (Sandbox Code Playgroud)
“Line2”将始终打印,true因为用户未经过身份验证。然后在 ViewModel 中我有:
fun getAuthResponse() = repo.getAuthResponse()
Run Code Online (Sandbox Code Playgroud)
以及内部活动:
setContent {
//...
val response = viewModel.getAuthResponse().collectAsState(initial = false).value
Log.d(TAG, "response: $response") //Line1
}
Run Code Online (Sandbox Code Playgroud)
由于 setContent 是一个可组合函数,因此当我打开应用程序时,它会触发两次。这意味着“Line1”处的日志语句被触发两次。当它第一次点火时,我得到:
response: false
currentUser: true
Run Code Online (Sandbox Code Playgroud)
因此,即使我在前一行调用了 getAuthResponse(),响应也会在之前打印。问题是,由于某种原因,即使当前用户为空,我也会在活动中打印出该用户不为空。当它第二次触发时,我得到了正确的数据:
response: true
currentUser: true
Run Code Online (Sandbox Code Playgroud)
为什么我得到一个非空的用户对象?trySend 会发出假数据吗?
kotlin firebase kotlin-coroutines android-jetpack-compose kotlin-flow
我有保持100个位置,每一个与所述一个公司的FireStore数据库lat和lng正确设置。我创建了一个方法来使用回调从数据库中实际读取数据:
public static void readLocations(MyCallback myCallback) {
locationsRef.get().addOnCompleteListener(task -> {
if (task.isSuccessful()) {
List<LocationModel> locationList = new ArrayList<>();
for (QueryDocumentSnapshot document : task.getResult()) {
LocationModel locationModel = document.toObject(LocationModel.class);
locationList.add(locationModel);
}
myCallback.onCallback(locationList);
}
});
}
Run Code Online (Sandbox Code Playgroud)
我正在使用 aLocationCallback来跟踪当前位置。使用下面的代码,我readLocations()在 LocationCallback 中调用方法来做一些关于某些距离的数学运算:
LocationCallback locationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
for (Location myLocation : locationResult.getLocations()) {
currentLocation = myLocation;
LatLng currentLatLng = new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude());
readLocations(locationList -> {
for (LocationModel lm : …Run Code Online (Sandbox Code Playgroud) 我正在尝试对从 API 获取的一些项目进行分页。我想一次加载 10 个项目。我需要的是始终在屏幕中央的所有内容之上显示进度。这是我尝试过的:
val items = viewModel.items.collectAsLazyPagingItems()
Box(
modifier = Modifier.fillMaxSize()
) {
LazyColumn {
items(
items = items
) { item ->
ProductCard(
item = item
)
}
items.apply {
when(loadState.refresh) {
is Loading -> item { ProgressBar() }
is Error -> //Log error
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的进度条:
@Composable
fun ProgressBar() {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
){
CircularProgressIndicator()
}
}
Run Code Online (Sandbox Code Playgroud)
问题是,当我启动应用程序时,进度条开始在 10 个加载项目的顶部加载。一旦我加载更多内容,它就会停留在现有项目的底部和新 10 个项目的顶部之间。如何让进度条始终位于屏幕中央,无论我加载多少页?
我有这段代码可以增加数据库中的值:
override fun incrementQuantity() = flow {
try {
emit(Result.Loading)
heroIdRef.update("quantity", FieldValue.increment(1)).await()
emit(Result.Success(true))
} catch (e: Exception) {
emit(Result.Failure(e))
}
}
Run Code Online (Sandbox Code Playgroud)
该函数是从 ViewModel 类中调用的,然后从可组合函数中读取如下响应:
when(val response = viewModel.incrementResponse) {
is Result.Loading -> showProgressBar()
is Result.Success -> Log.d("TAG", "Quantity incremented.")
is Result.Failure -> Log.d("TAG", response.e.message)
}
Run Code Online (Sandbox Code Playgroud)
这意味着在流程中我收到两个事件,第一个是Loading,第二个是数据或失败。我的问题是:
建议这样做吗?或者最好不使用流程并使用如下内容:
override fun incrementQuantity(): Result<Boolean> {
try {
heroIdRef.update("quantity", FieldValue.increment(1)).await()
Result.Success(true)
} catch (e: Exception) {
Result.Failure(e)
}
}
Run Code Online (Sandbox Code Playgroud)
在可组合项内部:
showProgressBar()
when(val response = viewModel.incrementResponse) {
is Result.Success -> {
hideProgressBar()
Log.d("TAG", "Quantity incremented.") …Run Code Online (Sandbox Code Playgroud) android kotlin kotlin-coroutines android-jetpack-compose kotlin-flow
我有这门课:
\nclass Product {\n public double price;\n\n public Product(double price) {\n this.price = price;\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n还有一张地图:
\nMap<Product, Integer> products = new HashMap<>();\nRun Code Online (Sandbox Code Playgroud)\n其中包含添加的几种产品,如下所示:
\nproducts.put(new Product(2.99), 2);\nproducts.put(new Product(1.99), 4);\nRun Code Online (Sandbox Code Playgroud)\n我想使用流计算所有乘积的总和乘以值?我试过:
\ndouble total = products.entrySet().stream().mapToDouble((k, v) -> k.getKey().price * v.getValue()).sum();\nRun Code Online (Sandbox Code Playgroud)\n但它无法编译,我得到 \xe2\x80\x9c无法解析方法getValue()\xe2\x80\x9d。
我预计:
\n(2.99 * 2) + (1.99 * 4) = 5.98 + 7.96 = 13.94\nRun Code Online (Sandbox Code Playgroud)\n android ×4
kotlin ×4
firebase ×2
java ×2
kotlin-flow ×2
dagger-hilt ×1
java-8 ×1
java-stream ×1