使用 Retrofit2 和 OkHttp3 在 API 获取请求后将 XML 布局转换为 Jetpack Compose

Posted

技术标签:

【中文标题】使用 Retrofit2 和 OkHttp3 在 API 获取请求后将 XML 布局转换为 Jetpack Compose【英文标题】:Convert XML Layout To Jetpack Compose after API Get Request with Retrofit2 and OkHttp3 【发布时间】:2021-12-05 23:01:43 【问题描述】:

我有一个要转换为 Jetpack Compose 的应用。我希望使用 Jetpack 创建卡片布局,而不是使用我拥有的当前 XML 文件。

我不确定如何处理我对 api 发出的 GET 请求调用的响应,并将数据解析为 Jetpack 而不是 XML 布局。

MainActivity.kt

class MainActivity : AppCompatActivity() 
    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setContent 
            MovieSpotterTheme() 
                setContentView(R.layout.activity_main)
            
        

        val request = ServiceBuilder.buildService(TmdbEndpoints::class.java)
        val call = request.getMovies(getString(R.string.api_key))

        call.enqueue(object : Callback<PopularMovies>
            override fun onResponse(call: Call<PopularMovies>, response: Response<PopularMovies>) 
                if (response.isSuccessful)
                    progress_bar.visibility = View.GONE
                    recyclerView.apply 
                        setHasFixedSize(true)
                        layoutManager = LinearLayoutManager(this@MainActivity)
                        adapter = MoviesAdapter(response.body()!!.results)
                    
                
            
            override fun onFailure(call: Call<PopularMovies>, t: Throwable) 
                Toast.makeText(this@MainActivity, "$t.message", Toast.LENGTH_SHORT).show()
            
        )
    

    private fun showToast(str: String) 
        Toast.makeText(this, str, Toast.LENGTH_SHORT).show()
    

响应通过 MoviesAdapter(xml 布局为 R.layout.movi​​e_item)

class MoviesAdapter(val movies: List<Result>): RecyclerView.Adapter<MoviesViewHolder>() 
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MoviesViewHolder 
        val view = LayoutInflater.from(parent.context).inflate(R.layout.movie_item, parent, false)
        return MoviesViewHolder(view)
    

    override fun getItemCount(): Int 
        return movies.size
    

    override fun onBindViewHolder(holder: MoviesViewHolder, position: Int) 
        return holder.bind(movies[position])
    


class MoviesViewHolder(itemView : View): RecyclerView.ViewHolder(itemView)
    private val photo:ImageView = itemView.findViewById(R.id.movie_photo)
    private val title:TextView = itemView.findViewById(R.id.movie_title)
    private val overview:TextView = itemView.findViewById(R.id.movie_overview)
    private val rating:TextView = itemView.findViewById(R.id.movie_rating)

    fun bind(movie: Result) 
        Glide.with(itemView.context).load("https://image.tmdb.org/t/p/w500$movie.poster_path").placeholder(R.drawable.space_dog_laika1).into(photo)
        title.text = "Title: " + movie.title
        overview.text = movie.overview
        rating.text = "User Score: " + movie.vote_average.toString()
    

movie_item 布局是一个相对布局,迁移文档都涵盖了约束布局的实例。

【问题讨论】:

【参考方案1】:

跳过适配器似乎是解决方案。我仍在解析数据,但将response.body()!!.results 发送到可组合函数允许我此时获取电影标题:

call.enqueue(object : Callback<PopularMovies>
            override fun onResponse(call: Call<PopularMovies>, response: Response<PopularMovies>) 
                if (response.isSuccessful)
                    progress_bar.visibility = View.GONE
                    recyclerView.apply 
                        setHasFixedSize(true)
                        layoutManager = LinearLayoutManager(this@MainActivity)
                        adapter = MoviesAdapter(response.body()!!.results)
                    
                
            
            override fun onFailure(call: Call<PopularMovies>, t: Throwable) 
                Toast.makeText(this@MainActivity, "$t.message", Toast.LENGTH_SHORT).show()
            
        )

改为:

call.enqueue(object : Callback<PopularMovies>
            override fun onResponse(call: Call<PopularMovies>, response: Response<PopularMovies>) 
                if (response.isSuccessful)
                    progress_bar.visibility = View.GONE
                    setContent
                        MovieList(response.body()!!.results)
                    
                
            
            override fun onFailure(call: Call<PopularMovies>, t: Throwable) 
                Toast.makeText(this@MainActivity, "$t.message", Toast.LENGTH_SHORT).show()
            
        )

Composables(在 MainActivity 下方)

@Composable
fun MovieList(results: List<Result>) 
    LazyColumn 
        items(results)  result ->
            MovieCardPreview(result)
        
    


@Composable
fun MovieCard(mov: Result)
    Column(modifier = Modifier.padding(all = 8.dp)) 
        Image(
            painter = painterResource(R.drawable.space_dog_laika1), // This is just a placeholder photo for now
            contentDescription = "Movie Poster",
            modifier = Modifier
                .size(40.dp)
                .clip(CircleShape)
                .border(1.5.dp, MaterialTheme.colors.secondary, CircleShape)
        )

        Row() 
            Text(text = mov.title)
        
    

【讨论】:

以上是关于使用 Retrofit2 和 OkHttp3 在 API 获取请求后将 XML 布局转换为 Jetpack Compose的主要内容,如果未能解决你的问题,请参考以下文章

Retrofit2 和 OkHttp3 仅在发生错误时使用缓存,例如网络错误或达到配额限制

使用 Retrofit2 和 OkHttp3 在 API 获取请求后将 XML 布局转换为 Jetpack Compose

http2 似乎不适用于 OkHttp3 和 retrofit2

为啥我在使用 Retrofit2 时得到“Type okhttp3.Call 没有类型参数”?

Android网络实战篇——OkHttp3(Retrofit2)五种缓存模式的实现

OkHttp3 + retrofit2 封装