繁体   English   中英

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

[英]Open an item as new activity from the RecyclerView and display certain data from JSON

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

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

这是按顺序排列的代码:

文章.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>>
}

回收适配器.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)
    }
}

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

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

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 的代码的 rest。

您可以带 1 个数据,即响应中的 id。 但首先您必须在文章 class 上添加属性 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()

然后解析响应。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM