如何设置从 API 获取数据到新活动中

问题描述 投票:0回答:2

我有一个新闻应用程序,我在其中使用 Retrofit 从 API 获取数据。我已经用 cardView 和 Recycler 视图显示了新闻。现在我想实施下一步,如果用户点击卡片,整个新闻应该显示在新活动中。但是要实现这一点,我不知道如何做到这一点。在这里,我提供了我的 MainActivity 、适配器类和用于改造的接口。我正在寻找实施下一步的帮助。

MainActivity.kt

class MainActivity : AppCompatActivity() {
    lateinit var adapter: NewsAdapter
   
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        getNews()
    }

    private fun getNews() {
        val news :Call<News> = NewsSeversis.newsIntence.getHeadlines("in",1)
        
        news.enqueue(object :Callback<News>{
            override fun onResponse(call: Call<News>, response: Response<News>) {
                //here response is a News response
                val news:News?=response.body()
                if (news!=null){
                    Log.d("response",news.toString())
                    adapter= NewsAdapter(news.articles)
                    newsList.adapter=adapter
                    newsList.layoutManager=LinearLayoutManager(this@MainActivity) 
                }
            }
            override fun onFailure(call: Call<News>, t: Throwable) {
                Log.d("response","error occur",t)
            }
        })
    } 
}

回收者视图的适配器类

class NewsAdapter (val artical: List<Artical>):RecyclerView.Adapter<NewsAdapter.articalViewHolder>(){
   inner class articalViewHolder(itemView: View):RecyclerView.ViewHolder(itemView)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): articalViewHolder {
        val view:View=LayoutInflater.from(parent.context).inflate(R.layout.item_layout,parent,false)
        return articalViewHolder(view)
    }

    override fun onBindViewHolder(holder: articalViewHolder, position: Int) {
        val articals:Artical=artical[position]
        holder.itemView.apply {
            newsTitle.text=articals.title
            newsDescription.text=articals.description
            Glide.with(context).load(articals.urlToImage).into(newsImage)

        }
    }

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

接口类

const val BASE_URL="https://newsapi.org/"
const val API_KEY="b461fea21cc242458825d1be951ebe1c"
 interface NewsInterface{
    
  @GET("v2/top-headlines?apiKey=$API_KEY")//@GET is to tell the it is a get request
    
  fun getHeadlines(@Query("country")country:String, @Query("page") page:Int) : Call<News> 
  
 }
object NewsSeversis {
   
    val newsIntence:NewsInterface
    init {
        val retrofit=Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .build()
       
        newsIntence=retrofit.create(NewsInterface::class.java)
    }

}

每个卡片视图的布局

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="16dp"
    app:cardUseCompatPadding="true"
    app:cardCornerRadius="8dp"
    app:cardElevation="4dp">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#F1F1F1"
        android:padding="16dp">

        <ImageView
            android:id="@+id/newsImage"
            android:layout_width="match_parent"
            android:layout_height="180dp"
            android:scaleType="centerCrop"
            android:src="@drawable/ic_launcher_background"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/newsTitle"
            style="@style/TextAppearance.AppCompat.Headline"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="10"
            android:maxLines="2"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            android:layout_marginTop="8dp"
            android:text="Title"
            app:layout_constraintTop_toBottomOf="@+id/newsImage" />

        <TextView
            android:id="@+id/newsDescription"
            style="@style/TextAppearance.AppCompat.Body1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="10"
            android:maxLines="2"
            android:text="Description"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            android:layout_marginTop="8dp"
            app:layout_constraintTop_toBottomOf="@+id/newsTitle" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>

主要活动布局

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/newsList"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

除此之外,我还有一个带有构造函数的 Artical 和一个新闻类,以及一个用于显示该活动的全部新闻的全新活动

新闻课

ata class News(
    val totalResults:Int,
    val articles:List<Artical>
    )

艺术课

data class Artical(
    val author:String,
    val title:String,
    val description:String,
    val url:String,
    val urlToImage:String)
android android-studio kotlin android-recyclerview retrofit2
2个回答
0
投票

要确定单击了哪个项目,我们需要一个接口,可以从中获取从 Adapter 到 Activity 的回调,因此在 Adapter 中创建一个接口类。 (在你的情况下,你可以在 NewsAdapter 的最后第二行创建它)

interface AdapterCallback {
    fun onClick(artical: Artical?)
}

然后我们需要在Adapter的Constructor中取一个这个接口的对象

class NewsAdapter (val artical: List<Artical>, callback: AdapterCallback): ...

然后我们必须在点击视图时使用回调对象。 (在你的情况下,在适配器类的 onBindViewHolder 中执行以下操作)

holder.itemView.setOnClickListener {
    callback.onClick(articals)
}

现在我们需要在我们的 Activity 中监听这个回调,所以我们需要通过以下方式在 Activity 中创建对象

private val adapterCallback: AdapterCallback =
        object : AdapterCallback {
            override fun onClick(artical: Artical?) {
                // Code here to navigate to desired Activity by passing required data in the intent (Example below)
                val intent = Intent(this, DestinationActivity::class.java)
                intent.putExtra("news_artical", artical)
                startActivity(intent)
            }
    }

现在我们的 Activity 中有 AdapterCallback 对象,我们需要将它传递给 Adapter

adapter = NewsAdapter(news.articles, adapterCallback)

注意:需要做Artical Class Parcelable

@Parcelize
data class Artical(
    val author: String,
    val title: String,
    val description: String,
    val url: String,
    val urlToImage: String
): Parcelable

0
投票

以下是从适配器获取项目点击活动回调的步骤。

在您的

NewsAdapter
课程中使用
HigherOrder Function
获得项目点击的回调。

1。首先更新 NewsAdapter

class NewsAdapter (
val artical: List<Artical>,
private val onItemClicked: (Artical) -> Unit
                ):RecyclerView.Adapter<NewsAdapter.articalViewHolder>(){
                    // your existing code 
             override fun onBindViewHolder(holder: articalViewHolder, position: Int) {
                    val articals:Artical=artical[position]
                    holder.itemView.apply {
                        newsTitle.text=articals.title
                        newsDescription.text=articals.description
                        Glide.with(context).load(articals.urlToImage).into(newsImage)
    // ADD THIS LINE 
        setOnClickListener { onItemClicked.invoke(articals) } 
            
                    }
                }

2。现在更新

MainActivity
中的代码,您正在创建
NewsAdapter
的对象。

// EXISTING CODE
adapter= NewsAdapter(news.articles){artical->
    // CODE TO LAUNCH THE NEW ACTIVITY       
    }
// EXISTING CODE

如有任何疑问,请随时询问。

© www.soinside.com 2019 - 2024. All rights reserved.