简体   繁体   中英

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

I'm making a simple app, that when the user is opening the app, to show every single article within this link's JSON data Spaceflight News API , when it opens the certain article from the user's choice, to open a new activity to show the summary of that certain article. The problem I am having is when I press lets say the second article of the list, it shows only the first element's summary. That's the only problem I am having. I have a screenshot of what element it gets that first element's summary data from:

My goal is to make every single element of that list aka the articles to display their own summary for each element of the list with a new activity with by using TextView to display the summary.

Here is the code by order:

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 Interface

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 (Because wanting to make it simple, it can be used as a Fragment instead of 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)
    }
}

My understanding is, that on the SummaryActivity you want to display the selected item's description.
If this is the case, then I don't understand why are you making the API call once again. The SummaryActivity should receive either the description of the selected item or, the Article instance.

Your summary Activity seems to have one text view:

summaryText = findViewById(R.id.summeryText)

But you are resetting it with every article:

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

So basically, only the last article's summary will be shown.

Don't do that.

Instead you could pass the summary (and other information) to the Activity:

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

Then set it on the SummaryActivity:

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

And then remove the rest of the code that makes an API call again.

you can bring 1 data, that is the id from the response. But first you must add property id on your Article class.

    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)
        }
    } 

then on your SummaryActivity

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

then parsing the response.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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