Home > Software design >  Open an item as new activity from the RecyclerView and display certain data from JSON
Open an item as new activity from the RecyclerView and display certain data from JSON

Time:12-05

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

My goal is to make every single element of that list a.k.a. 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)
    }
}

CodePudding user response:

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.

CodePudding user response:

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.

  • Related