从 RecyclerView 打开一个项目作为新活动并显示来自 JSON 的某些数据

Posted

技术标签:

【中文标题】从 RecyclerView 打开一个项目作为新活动并显示来自 JSON 的某些数据【英文标题】:Open an item as new activity from the RecyclerView and display certain data from JSON 【发布时间】:2022-01-10 15:13:41 【问题描述】:

我正在制作一个简单的应用程序,当用户打开应用程序时,显示此链接的 JSON 数据Spaceflight News API 中的每一篇文章,当它从用户选择的特定文章中打开时,打开一个新活动显示该特定文章的摘要。我遇到的问题是当我按下让我们说列表的第二篇文章时,它只显示第一个元素的摘要。这是我唯一的问题。我有一个它从哪个元素获取第一个元素的摘要数据的屏幕截图:

我的目标是通过使用 TextView 显示摘要,使该列表中的每个元素(也称为文章)为列表中的每个元素显示自己的摘要,并带有新的活动。

这是按顺序排列的代码:

Article.java

package com.example.spaceflightnews.get;

public class Article 
    public String getTitle() 
        return title;
    

//Trying to get this data for each individual item element within the RecycleView
    public String getSummary() 
        return summary;
    

    public String getPublishedAt() 
        return publishedAt;
    

    public Article(String title, String summary, String publishedAt) 
        this.title = title;
        this.summary = summary;
        this.publishedAt = publishedAt;
    

    private final String title;
    private final String summary;
    private final String publishedAt;

SpaceflightAPI.kt 接口

package com.example.spaceflightnews.spaceflightNewsAPI

import com.example.spaceflightnews.get.Article
import retrofit2.Call
import retrofit2.http.GET

interface SpaceflightAPI 
    @GET("articles")
    fun getArticles(): Call<List<Article>>

RecyclerAdapter.kt

package com.example.spaceflightnews

import android.content.Context
import android.content.Intent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.example.spaceflightnews.get.Article

class RecyclerAdapter(var listItems: List<Article>, var context: Context) : RecyclerView.Adapter<RecyclerAdapter.ViewHolder>() 

    //Connecting the context then making a LayoutInflater along with it's context of the activity, then selecting the card_items.xml, then using the ViewGroup, making sure
    //to put attachToRoot into false
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder 
        this.context = parent.context
        val v = LayoutInflater.from(context)
            .inflate(R.layout.card_items, parent, false)

        return ViewHolder(v)
    

    //We connect the ViewHolder class that is in the ViewGroup and then using the those texts to get the JSON data and using listItems original position of that list
    override fun onBindViewHolder(holder: ViewHolder, position: Int) 
        val listItem = listItems[position]

        holder.titleText.text = listItem.title
        holder.publishedAtText.text = "Published: $listItem.publishedAt"
    

    //Getting the item count of the max size of the list of items
    override fun getItemCount(): Int = listItems.size

    //Initializing the TextViews to it's ID here!
    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) 
        var titleText: TextView = itemView.findViewById(R.id.titleText)
        var publishedAtText: TextView = itemView.findViewById(R.id.publishedAtText)

        init 
            itemView.setOnClickListener 
                val intent = Intent(itemView.context, SummeryActivity::class.java)
                itemView.context.startActivity(intent)
            
        
    

MainActivity.kt

package com.example.spaceflightnews

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.spaceflightnews.get.Article
import com.example.spaceflightnews.spaceflightNewsAPI.SpaceflightAPI
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

class MainActivity : AppCompatActivity() 
    //Getting the RecyclerView and the Adapter ready
    private lateinit var recyclerView: RecyclerView

    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        //Connecting to it's ID from the XML
        recyclerView = findViewById(R.id.recyclerView)

        //RetroFit
        val retrofit = Retrofit.Builder()
            .baseUrl("https://api.spaceflightnewsapi.net/v3/")
            .addConverterFactory(GsonConverterFactory.create())
            .build()

        //Creating the SpaceFlight interface and then assigning the same list to get the list of articles within the interface SpaceflightAPI
        val jsonSpaceApi = retrofit.create(SpaceflightAPI::class.java)
        val call: Call<List<Article>> = jsonSpaceApi.getArticles()

        //Instead of using execute, we use enqueue to implement an interface Callback
        call.enqueue(object : Callback<List<Article>> 
            override fun onResponse(call: Call<List<Article>>, response: Response<List<Article>>) 
                //We get the List of Article class as we assign a new variable to connect is as a response.
                val articles = response.body()

                //We are connecting the RecyclerView to it's LayoutManager, using LinearLayoutManager and connecting to it's context.
                recyclerView.layoutManager = LinearLayoutManager(this@MainActivity)
                //Then we make the RecyclerAdapter class for the RecyclerView, it's parameters is the List of Article class and it's context.
                recyclerView.adapter = RecyclerAdapter(articles!!, this@MainActivity)
            

            override fun onFailure(call: Call<List<Article>>, t: Throwable) 
                Toast.makeText(this@MainActivity, "$t.message", Toast.LENGTH_SHORT).show()
            
        )
    

SummaryActivity.kt(因为想简单,所以可以当成Fragment来代替Activity)

package com.example.spaceflightnews

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.MenuItem
import android.widget.TextView
import android.widget.Toast
import com.example.spaceflightnews.get.Article
import com.example.spaceflightnews.spaceflightNewsAPI.SpaceflightAPI
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

class SummaryActivity : AppCompatActivity() 
    private lateinit var summaryText: TextView

    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_summery)
        //Assigning the ActionBar's support
        val actionBar = supportActionBar
        actionBar!!.setDisplayHomeAsUpEnabled(true)

        summaryText = findViewById(R.id.summeryText)

        val retrofit = Retrofit.Builder()
            .baseUrl("https://api.spaceflightnewsapi.net/v3/")
            .addConverterFactory(GsonConverterFactory.create())
            .build()

        val jsonSpaceApi = retrofit.create(SpaceflightAPI::class.java)
        val call: Call<List<Article>> = jsonSpaceApi.getArticles()

        call.enqueue(object : Callback<List<Article>> 
            override fun onResponse(call: Call<List<Article>>, response: Response<List<Article>>) 
                val articles = response.body()
                for (article in articles!!) 
                    summaryText.text = article.summary
                
            

            override fun onFailure(call: Call<List<Article>>, t: Throwable) 
                summaryText.text = t.message
                Toast.makeText(applicationContext, "$t.message", Toast.LENGTH_LONG).show()
            

        )
    

    //This will make the button on the Top Left to destroy the activity and return and returns back to the main activity.
    override fun onOptionsItemSelected(item: MenuItem): Boolean 
        when (item.itemId) 
            android.R.id.home -> finish()
        
        return super.onOptionsItemSelected(item)
    

【问题讨论】:

尝试重新表述您的问题。我,一方面,不清楚你的问题是什么。此外,您发布的信息太多了 - 没有人会审查它。将其煮沸至最低限度。 ***.com/help/how-to-ask @dominicoder 已编辑,请您再看一遍确认问题好吗? 【参考方案1】:

我的理解是,您希望在 SummaryActivity 上显示所选项目的描述。 如果是这种情况,那么我不明白您为什么要再次进行 API 调用。 SummaryActivity 应该接收所选项目的描述或 Article 实例。

【讨论】:

问题是它没有收到它应该收到的东西。所以基本上我想从 Article 实例中单独显示 JSON 数据中它自己的摘要/描述,除非我必须连接 ID 并打开单独数量的活动来显示它自己的摘要。 我会去连接 ID。您可以将文章存储在本地数据库中,也可以存储在内存存储库中(取决于上下文),并在意图或片段参数中作为额外的 ID 传递。【参考方案2】:

您的摘要活动似乎只有一个文本视图:

summaryText = findViewById(R.id.summeryText)

但是你在每篇文章都重置它:

for (article in articles!!) 
    summaryText.text = article.summary

所以基本上,只会显示最后一篇文章的摘要。

不要那样做。

相反,您可以将摘要(和其他信息)传递给 Activity:

itemView.setOnClickListener 
    val summary = getClickedItemSummary()
    val intent = Intent(itemView.context, SummeryActivity::class.java)
    intent.putExtra("Summary", summary)
    itemView.context.startActivity(intent)

然后在SummaryActivity上设置:

summaryText = findViewById(R.id.summeryText)
summaryText.text = intent.getString("Summary")

然后删除再次调用 API 的其余代码。

【讨论】:

getClickedItemSummary() 这是我必须创建的新方法吗?如果是,你能告诉我如何格式化它吗? 是的,它是伪代码。如何格式化?它将根据您的 IDE 设置进行格式化。实现将由您根据您的逻辑填写。【参考方案3】:

您可以带 1 个数据,即响应中的 id。但首先您必须在 Article 类中添加属性 ID。

    override fun onBindViewHolder(holder: ViewHolder, position: Int) 
        val listItem = listItems[position]

        holder.titleText.text = listItem.title
        holder.publishedAtText.text = "Published: $listItem.publishedAt"
        holder.itemView.setOnClickListener 
            val intent = Intent(holder.itemView.context, SummeryActivity::class.java)
            intent.putExtra("id",listItem.id);
            holder.itemView.itemView.context.startActivity(intent)
        
     

然后在您的 SummaryActivity 上

   val articleId = intent.getString("id")
   val retrofit = Retrofit.Builder()
        .baseUrl("https://api.spaceflightnewsapi.net/v3/articles/$articleId")
        .addConverterFactory(GsonConverterFactory.create())
        .build()

然后解析响应。

【讨论】:

以上是关于从 RecyclerView 打开一个项目作为新活动并显示来自 JSON 的某些数据的主要内容,如果未能解决你的问题,请参考以下文章

从片段中获取意图值后,我如何在 recyclerview 项目中实现单击

将水平 RecyclerView 作为项目放置在垂直 RecyclerView 中时的自动滚动问题

使用 GridLayoutManager 将项目粘贴到 RecyclerView 的底部

从 IntentService 访问 Recyclerview 中的 TextView 和 Progressbar

为啥 recyclerview 返回错误的项目?

Android - 在 RecyclerView 中单击的项目上打开新活动 [重复]