首页 > 解决方案 > 如何从 API 显示一定数量的图像 - Kotlin - 改造

问题描述

我正在从 API 调用数据以显示它以供使用,但在我的情况下,我想显示 API 的最新 4 个图像,我不想调用所有这些图像

那么正确的方法是什么?

这是我的代码:

界面:

interface facebookInterface {

@GET(" ")

fun getServices(): Call<List<facebookData>>

companion object Factory {
    fun create(): facebookInterface {
        val retrofit = Retrofit.Builder()
            .addConverterFactory(GsonConverterFactory.create())
            .baseUrl("API_URL")
            .build()

        return retrofit.create(facebookInterface::class.java)
    }
}
}

适配器:

class facebookAdapter(var countryList: List<facebookData>, var activity: MainActivity): RecyclerView.Adapter<facebookAdapter.ViewHolder>(){
lateinit var context: Context
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): facebookAdapter.ViewHolder {
    context = parent.context!!
    val view = LayoutInflater.from(context).inflate(R.layout.facebook_list_item, parent, false)
    return ViewHolder(view)
}

override fun getItemCount(): Int {
    return countryList.size
}

override fun onBindViewHolder(holder: facebookAdapter.ViewHolder, position: Int) {
    holder.name.text = countryList[position].source
    holder.capital.text = countryList[position].imageLink



    Picasso.get()
        .load(countryList[position].imageUrl)
        .memoryPolicy(MemoryPolicy.NO_CACHE, MemoryPolicy.NO_STORE)
        .networkPolicy(NetworkPolicy.NO_CACHE, NetworkPolicy.NO_STORE)
        .into(holder.thumbnailUrl)




}

class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView){
    val name: TextView = itemView.findViewById(R.id.country_name)
    val capital: TextView = itemView.findViewById(R.id.country_capital)
    val thumbnailUrl: ImageView = itemView.findViewById(R.id.country_flag)

}

}

list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/frame_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<androidx.cardview.widget.CardView
    android:id="@+id/list_card"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:cardCornerRadius="4dp"
    app:contentPadding="8dp">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/list_constraint"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/country_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:fontFamily="monospace"
            android:text="TextView"
            android:textSize="24sp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/country_capital"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:fontFamily="monospace"
            android:text="TextView"
            android:textSize="18sp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/country_name" />

        <ImageView
            android:id="@+id/country_flag"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_marginTop="8dp"
            android:layout_marginEnd="8dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</FrameLayout>

活动:

val recyclerView: RecyclerView = findViewById(R.id.list_recycler4)
    recyclerView.layoutManager = LinearLayoutManager(this)
    val facebookInterface = facebookInterface.Factory.create()
    val facebok: Call<List<facebookData>> = facebookInterface.getServices()
    facebok.enqueue(object : Callback<List<facebookData>> {
        override fun onFailure(call: Call<List<facebookData>>, t: Throwable) {
            Log.d("xxxx", t.toString())
            Toast.makeText(this@MainActivity, t.message, Toast.LENGTH_SHORT).show()
        }
        override fun onResponse(
            call: Call<List<facebookData>>,
            response: Response<List<facebookData>>
        ) {
            Log.d("xxxx", response.body().toString())
            val list = response.body()!!
            recyclerView.adapter = facebookAdapter(list, this@MainActivity)
        }
    })

数据类:

data class facebookData (
val  imageUrl : String,
val imageLink: String,
val source: String
    )

我正在获取数据,我可以在设备上看到它,但有没有办法只显示来自 API 的最新 4 张图像?

以及如何链接每个图像的 url,以便用户可以转到每个图像的 url

“英语不是我的母语,如果你不明白我会解释更多”

标签: javaandroidapikotlinretrofit

解决方案


正如 Teo 所说,您最好将过滤器直接应用于您的 API 调用,但如果这不可能,您可以删除您收到的列表。我能想到的主要有两种方法,可以得到你想要的,首先是制作一个子列表,然后按如下方式分配适配器。

val trimmedList = if(list.size > 4){
            list.subList(fromIndex = 0, toIndex = 3)
        } else {
            list
        }
    recyclerView.adapter = facebookAdapter(trimmedList , this@MainActivity)

在 Recycler View Adapter 中覆盖 itemCount 方法的第二种方法,同样的逻辑应该适用于那里。如下。

override fun getItemCount(): Int {
            return if(countryList.size > 4) {
                4
            } else {
                countryList.size
            }
        }

对于您答案的第二部分,我添加了以下代码供您参考,但我仍然相信您最好了解正在发生的事情。

要在浏览器中打开 url,首先需要从 Adapter 回调到 MainActivity。

您的适配器将被修改如下。

class facebookAdapter(var countryList: List<facebookData>,
private val facebookAdapterCallback: FacebookAdapterCallback)
    : RecyclerView.Adapter<facebookAdapter.ViewHolder>(){
    lateinit var context: Context
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): facebookAdapter.ViewHolder {
        context = parent.context!!
        val view = LayoutInflater.from(context).inflate(R.layout.facebook_list_item, parent, false)
        return ViewHolder(view)
    }

    override fun getItemCount(): Int {
        return countryList.size
    }

    override fun onBindViewHolder(holder: facebookAdapter.ViewHolder, position: Int) {
        holder.name.text = countryList[position].source
        holder.capital.text = countryList[position].imageLink

        holder.thumbnailUrl.setOnClickListener {
            facebookAdapterCallback.onFacebookAdapterItemClick(countryList[position])
        }

        Picasso.get()
                .load(countryList[position].imageUrl)
                .memoryPolicy(MemoryPolicy.NO_CACHE, MemoryPolicy.NO_STORE)
                .networkPolicy(NetworkPolicy.NO_CACHE, NetworkPolicy.NO_STORE)
                .into(holder.thumbnailUrl)
    }

    class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView){
        val name: TextView = itemView.findViewById(R.id.country_name)
        val capital: TextView = itemView.findViewById(R.id.country_capital)
        val thumbnailUrl: ImageView = itemView.findViewById(R.id.country_flag)
    }

    interface FacebookAdapterCallback{
        fun onFacebookAdapterItemClick(data: facebookData)
    }
}

接下来,我们将不得不修改您的活动,以在其中实现上述接口

class MainActivity : AppCompatActivity(), facebookAdapter.FacebookAdapterCallback {
    override fun onFacebookAdapterItemClick(data: facebookData) {
        openLinkInBrowser(this@MainActivity, data.imageLink)
    }

    fun openLinkInBrowser(context: Context, url: String) {
        try {
            val url = if (Uri.parse(url).scheme == null || !url.startsWith("https://") && !url.startsWith("http://")) {
                "https://$url"
            } else url
            val webPage: Uri = Uri.parse(url)
            val intent = Intent(Intent.ACTION_VIEW, webPage)
            if (intent.resolveActivity(context.packageManager) != null) {
                context.startActivity(intent)
            } else {
                Toast.makeText(context, "No App Available for this action", Toast.LENGTH_SHORT).show()
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
}

我还添加了一个帮助方法来在浏览器中打开链接,它使用默认的 Android Intents 并检查可以执行此操作的可用应用程序。我们还检查 URL 是否已添加httphttps附加,否则我们添加它。

虽然我已经为您提供了代码,但我仍然建议您在执行此操作之前了解正在发生的事情。


推荐阅读