如何掩盖 android Studio 中的加载时间延迟?

How to cover up the loading time lag in android Studio?

我在 Android Studio 中制作了一个从网站导入数据的应用程序...当我打开该应用程序时,要导入数据的卡片视图是空的,并在一段时间后加载.我想知道是否有任何方法可以掩盖它,以便在加载它之前我的闪屏一直停留在那里。这是显示延迟的视频:

Card View loading time lag

编辑: 这是电影适配器:

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 中创建一个与启动画面完全相同的启动画面视图,并在后台从网络加载所有数据时首先显示它,一旦数据到达,隐藏此启动画面查看和显示应用的主屏幕。

您可以改用微光效果来显示背景中的数据加载。