如何掩盖 android Studio 中的加载时间延迟?
How to cover up the loading time lag in android Studio?
我在 Android Studio 中制作了一个从网站导入数据的应用程序...当我打开该应用程序时,要导入数据的卡片视图是空的,并在一段时间后加载.我想知道是否有任何方法可以掩盖它,以便在加载它之前我的闪屏一直停留在那里。这是显示延迟的视频:
编辑: 这是电影适配器:
class MoviesAdapter(
private var movies: MutableList<Movie>,
private val onMovieClick: (movie: Movie) -> Unit,
) : RecyclerView.Adapter<MoviesAdapter.MovieViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MovieViewHolder {
val view = LayoutInflater
.from(parent.context)
.inflate(R.layout.item_movie, parent, false)
return MovieViewHolder(view)
}
override fun getItemCount(): Int = movies.size
override fun onBindViewHolder(holder: MovieViewHolder, position: Int) {
holder.bind(movies[position])
}
fun appendMovies(movies: List<Movie>) {
this.movies.addAll(movies)
notifyItemRangeInserted(
this.movies.size,
movies.size - 1
)
}
inner class MovieViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val poster: ImageView = itemView.findViewById(R.id.item_movie_poster)
fun bind(movie: Movie) {
itemView.setOnClickListener { onMovieClick.invoke(movie) }
Glide.with(itemView)
.load("https://image.tmdb.org/t/p/w342${movie.posterPath}")
.transform(CenterCrop())
.into(poster)
}
}
}
我的main_activity_xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg_gradient"
android:fitsSystemWindows="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="25dp"
android:layout_marginEnd="16dp"
android:text="@string/discover"
android:textColor="@android:color/white"
android:textSize="45sp"
android:textStyle="bold" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:text="@string/popular"
android:textColor="@android:color/white"
android:textSize="22sp"
android:textStyle="bold" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:text="@string/most_popular_movies" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/popular_movies"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:clipToPadding="false"
android:paddingStart="16dp"
android:paddingEnd="16dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:text="@string/top_rated"
android:textColor="@android:color/white"
android:textSize="22sp"
android:textStyle="bold" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:text="@string/highest_rated_movies" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/top_rated_movies"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:clipToPadding="false"
android:paddingStart="16dp"
android:paddingEnd="16dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:text="@string/upcoming"
android:textColor="@android:color/white"
android:textSize="22sp"
android:textStyle="bold" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:text="@string/stay_updated" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/upcoming_movies"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginBottom="16dp"
android:clipToPadding="false"
android:paddingStart="16dp"
android:paddingEnd="16dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:text="@string/now_playing"
android:textColor="@android:color/white"
android:textSize="22sp"
android:textStyle="bold" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:text="@string/now_in_Cinemas" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/now_playing_movies"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginBottom="10dp"
android:clipToPadding="false"
android:paddingStart="16dp"
android:paddingEnd="16dp" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
Api键:
interface Api {
@GET("movie/popular")
fun getPopularMovies(
@Query("api_key") apiKey: String =
"eff7d87eb14cdf1fb273414692d3e3a8",
@Query("page") page: Int,
): Call<GetMoviesResponse>
}
Api 加载程序:
api.getPopularMovies(page = page)
.enqueue(object : Callback<GetMoviesResponse> {
override fun onResponse(
call: Call<GetMoviesResponse>,
response: Response<GetMoviesResponse>,
) {
if (response.isSuccessful) {
val responseBody = response.body()
if (responseBody != null) {
onSuccess.invoke(responseBody.movies)
} else {
onError.invoke()
}
} else {
onError.invoke()
}
}
override fun onFailure(call: Call<GetMoviesResponse>, t:
Throwable) {
onError.invoke()
}
})
还有什么我应该指定的吗?
如果您想在启动画面中等待,您需要在启动画面中提出该请求。
当你有一个成功的响应时,你然后导航并通过 args/intent extras 传递数据,假设这是一个不同的 fragment/activity。
然后,当您设置创建列表适配器时,您只需将此列表传递给构造函数并设置所有内容,就像您可能已经拥有的那样。
希望对您有所帮助,但如果还不够清楚,请告诉我!
没有代码很难回答这个问题,但您始终可以使用在卡片视图的数据准备好之前显示“正在加载”状态但保持 space 的 ViewSwitcher,因此 UI 不会跳转,然后在加载数据后显示卡片视图。
可能是这样的:
sealed class CardData {
object Loading: CardData()
class Info(val items: List<CardInfo>): CardData()
}
fun loadData() {
viewModel.cardData.observe { cardData ->
when(cardData) {
is Loading -> {
binding.switcher.displayedChild = 0
}
is Info -> {
binding.switcher.displayedChild = 1
binding.listOfCards.items = cardData.items
}
}
}
针对您的具体情况:
// display the loading view before making the call
binding.switcher.displayedChild = 0
api.getPopularMovies(page = page)
.enqueue(object : Callback<GetMoviesResponse> {
override fun onResponse(
call: Call<GetMoviesResponse>,
response: Response<GetMoviesResponse>,
) {
if (response.isSuccessful) {
val responseBody = response.body()
if (responseBody != null) {
onSuccess.invoke(responseBody.movies)
} else {
onError.invoke()
}
} else {
onError.invoke()
}
}
override fun onFailure(call: Call<GetMoviesResponse>, t:
Throwable) {
onError.invoke()
}
})
// in your onSuccess()
private void onSuccess(List<Movies> movies) {
binding.switcher.displayedChild = 1
listAdapter.items = movies
listAdapter.notifyDatasetChanged()
}
// in your onError()
private void onError() {
binding.switcher.displayedChild = 2 // you can add a third child for errors
}
那么 XML 将类似于(缺少属性):
<ViewSwitcher
android:id="@+id/switcher">
<!-- child 0 - loading state -->
<ProgressBar
android:id="@+id/loader"
/>
<!-- child 1 - movies state -->
<RecyclerView
android:id="@+id/movies"
/>
<!-- child 2 - error state -->
<TextView
android:id="@id/error_text"
/>
</ViewSwitcher>
您可以在主 activity 中创建一个与启动画面完全相同的启动画面视图,并在后台从网络加载所有数据时首先显示它,一旦数据到达,隐藏此启动画面查看和显示应用的主屏幕。
您可以改用微光效果来显示背景中的数据加载。
我在 Android Studio 中制作了一个从网站导入数据的应用程序...当我打开该应用程序时,要导入数据的卡片视图是空的,并在一段时间后加载.我想知道是否有任何方法可以掩盖它,以便在加载它之前我的闪屏一直停留在那里。这是显示延迟的视频:
编辑: 这是电影适配器:
class MoviesAdapter(
private var movies: MutableList<Movie>,
private val onMovieClick: (movie: Movie) -> Unit,
) : RecyclerView.Adapter<MoviesAdapter.MovieViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MovieViewHolder {
val view = LayoutInflater
.from(parent.context)
.inflate(R.layout.item_movie, parent, false)
return MovieViewHolder(view)
}
override fun getItemCount(): Int = movies.size
override fun onBindViewHolder(holder: MovieViewHolder, position: Int) {
holder.bind(movies[position])
}
fun appendMovies(movies: List<Movie>) {
this.movies.addAll(movies)
notifyItemRangeInserted(
this.movies.size,
movies.size - 1
)
}
inner class MovieViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val poster: ImageView = itemView.findViewById(R.id.item_movie_poster)
fun bind(movie: Movie) {
itemView.setOnClickListener { onMovieClick.invoke(movie) }
Glide.with(itemView)
.load("https://image.tmdb.org/t/p/w342${movie.posterPath}")
.transform(CenterCrop())
.into(poster)
}
}
}
我的main_activity_xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg_gradient"
android:fitsSystemWindows="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="25dp"
android:layout_marginEnd="16dp"
android:text="@string/discover"
android:textColor="@android:color/white"
android:textSize="45sp"
android:textStyle="bold" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:text="@string/popular"
android:textColor="@android:color/white"
android:textSize="22sp"
android:textStyle="bold" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:text="@string/most_popular_movies" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/popular_movies"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:clipToPadding="false"
android:paddingStart="16dp"
android:paddingEnd="16dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:text="@string/top_rated"
android:textColor="@android:color/white"
android:textSize="22sp"
android:textStyle="bold" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:text="@string/highest_rated_movies" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/top_rated_movies"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:clipToPadding="false"
android:paddingStart="16dp"
android:paddingEnd="16dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:text="@string/upcoming"
android:textColor="@android:color/white"
android:textSize="22sp"
android:textStyle="bold" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:text="@string/stay_updated" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/upcoming_movies"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginBottom="16dp"
android:clipToPadding="false"
android:paddingStart="16dp"
android:paddingEnd="16dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:text="@string/now_playing"
android:textColor="@android:color/white"
android:textSize="22sp"
android:textStyle="bold" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:text="@string/now_in_Cinemas" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/now_playing_movies"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginBottom="10dp"
android:clipToPadding="false"
android:paddingStart="16dp"
android:paddingEnd="16dp" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
Api键:
interface Api {
@GET("movie/popular")
fun getPopularMovies(
@Query("api_key") apiKey: String =
"eff7d87eb14cdf1fb273414692d3e3a8",
@Query("page") page: Int,
): Call<GetMoviesResponse>
}
Api 加载程序:
api.getPopularMovies(page = page)
.enqueue(object : Callback<GetMoviesResponse> {
override fun onResponse(
call: Call<GetMoviesResponse>,
response: Response<GetMoviesResponse>,
) {
if (response.isSuccessful) {
val responseBody = response.body()
if (responseBody != null) {
onSuccess.invoke(responseBody.movies)
} else {
onError.invoke()
}
} else {
onError.invoke()
}
}
override fun onFailure(call: Call<GetMoviesResponse>, t:
Throwable) {
onError.invoke()
}
})
还有什么我应该指定的吗?
如果您想在启动画面中等待,您需要在启动画面中提出该请求。
当你有一个成功的响应时,你然后导航并通过 args/intent extras 传递数据,假设这是一个不同的 fragment/activity。
然后,当您设置创建列表适配器时,您只需将此列表传递给构造函数并设置所有内容,就像您可能已经拥有的那样。
希望对您有所帮助,但如果还不够清楚,请告诉我!
没有代码很难回答这个问题,但您始终可以使用在卡片视图的数据准备好之前显示“正在加载”状态但保持 space 的 ViewSwitcher,因此 UI 不会跳转,然后在加载数据后显示卡片视图。
可能是这样的:
sealed class CardData {
object Loading: CardData()
class Info(val items: List<CardInfo>): CardData()
}
fun loadData() {
viewModel.cardData.observe { cardData ->
when(cardData) {
is Loading -> {
binding.switcher.displayedChild = 0
}
is Info -> {
binding.switcher.displayedChild = 1
binding.listOfCards.items = cardData.items
}
}
}
针对您的具体情况:
// display the loading view before making the call
binding.switcher.displayedChild = 0
api.getPopularMovies(page = page)
.enqueue(object : Callback<GetMoviesResponse> {
override fun onResponse(
call: Call<GetMoviesResponse>,
response: Response<GetMoviesResponse>,
) {
if (response.isSuccessful) {
val responseBody = response.body()
if (responseBody != null) {
onSuccess.invoke(responseBody.movies)
} else {
onError.invoke()
}
} else {
onError.invoke()
}
}
override fun onFailure(call: Call<GetMoviesResponse>, t:
Throwable) {
onError.invoke()
}
})
// in your onSuccess()
private void onSuccess(List<Movies> movies) {
binding.switcher.displayedChild = 1
listAdapter.items = movies
listAdapter.notifyDatasetChanged()
}
// in your onError()
private void onError() {
binding.switcher.displayedChild = 2 // you can add a third child for errors
}
那么 XML 将类似于(缺少属性):
<ViewSwitcher
android:id="@+id/switcher">
<!-- child 0 - loading state -->
<ProgressBar
android:id="@+id/loader"
/>
<!-- child 1 - movies state -->
<RecyclerView
android:id="@+id/movies"
/>
<!-- child 2 - error state -->
<TextView
android:id="@id/error_text"
/>
</ViewSwitcher>
您可以在主 activity 中创建一个与启动画面完全相同的启动画面视图,并在后台从网络加载所有数据时首先显示它,一旦数据到达,隐藏此启动画面查看和显示应用的主屏幕。
您可以改用微光效果来显示背景中的数据加载。