Reputation: 716
I have this app where I have a recycler view that gets the images and titles of news. Then, when the user clicks on the image, the news is supposed to open and show the image, title and then the author and description of the news. The thing is, the author and the description were not on the recycler view and I want to add them to the second activity that shows the detail of the news. How can I do that since the data isn't bound to any view yet and, therefore, I can't pass it through an intent (I think)?
This is my recycler adapter with the setOnClickListener that triggers the second activity:
package com.example.newsapp
import android.content.Intent
import android.icu.text.CaseMap
import android.net.Uri
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.ImageView
import android.widget.TextView
import androidx.core.content.ContextCompat.startActivity
import androidx.recyclerview.widget.RecyclerView
import com.example.newsapp.databinding.NewsItemBinding
import com.squareup.picasso.Picasso
class RecyclerAdapter (
private var Titles: List<String>,
private var Images: List<String>,
private var Authors: List<String>,
private var Descriptions: List<String>
) : RecyclerView.Adapter<RecyclerAdapter.ViewHolder>(){
inner class ViewHolder(
view: View
): RecyclerView.ViewHolder(view){
private val binding = NewsItemBinding.bind(view)
val itemTitle: TextView = binding.tvTitle
val itemImage: ImageView = binding.ivNewsImage
fun bind(urlToImage:String){
Picasso.get().load(urlToImage).into(binding.ivNewsImage)
}
init {
itemImage.setOnClickListener{
val intent = Intent(view.context, PostActivity::class.java)
intent.putExtra("title",itemTitle.text)
intent.putExtra("source",)
view.context.startActivity(intent)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.news_item, parent, false)
return ViewHolder(v)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.itemTitle.text = Titles[position]
val itemImage = Images[position]
holder.bind(itemImage)
}
override fun getItemCount(): Int {
return Titles.size
}
}
This is the second activity that needs to have the extra details:
package com.example.newsapp
import android.media.Image
import android.os.Bundle
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import com.example.newsapp.databinding.ActivityPostBinding
class PostActivity: AppCompatActivity() {
private lateinit var binding: ActivityPostBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_post)
binding = ActivityPostBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
//get title
var detailTitle = intent.getStringExtra("title")
binding.tvTitleItem.text = detailTitle
//get image
//get author
//get description
}
}
This is the API response:
package com.example.newsapp
import com.google.gson.annotations.SerializedName
data class NewsResponse (
@SerializedName("status") var Status: String,
@SerializedName("totalResults") var totalResults: Int,
@SerializedName("articles") var Articles: List<ArticlesData>
)
data class ArticlesData (
@SerializedName("source") var Source: SourceData,
@SerializedName("author") var Author: String,
@SerializedName("title") var Title: String,
@SerializedName("description") var Description: String,
@SerializedName("url") var Url: String,
@SerializedName("urlToImage") var urlToImage: String,
@SerializedName("publishedAt") var publishedAt: String,
@SerializedName("content") var Content: String
)
data class SourceData (
@SerializedName("name") var Name: String,
)
This is the Main activity:
package com.example.newsapp
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.newsapp.databinding.ActivityMainBinding
import kotlinx.coroutines.*
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.lang.Exception
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var adapter: RecyclerAdapter
private val newsTitles = mutableListOf<String>()
private val newsImages = mutableListOf<String>()
private val newsAuthors = mutableListOf<String>()
private val newsDescriptions = mutableListOf<String>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
makeAPIRequest()
}
private fun initRecyclerView() {
adapter = RecyclerAdapter( newsTitles, newsImages, newsAuthors, newsDescriptions)
binding.rvNews.layoutManager = LinearLayoutManager(this)
binding.rvNews.adapter = adapter
}
private fun addToList(title:String, image:String, author:String, description:String){
newsTitles.add(title)
newsImages.add(image)
newsAuthors.add(author)
newsDescriptions.add(description)
}
private fun makeAPIRequest() {
val api = Retrofit.Builder()
.baseUrl("https://newsapi.org/")
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(APIService::class.java)
GlobalScope.launch(Dispatchers.IO){
val response = api.getNews()
val posts = response.body()
try{
if (posts != null) {
for(art in posts.Articles){
Log.i("Main Activity", "Result = $art")
addToList(art.Title,art.urlToImage, art.Author, art.Description)
}
}
withContext(Dispatchers.Main){
initRecyclerView()
}
} catch (e:Exception){
Log.e("Main Activity", e.toString())
}
}
}
}
Upvotes: 0
Views: 61
Reputation: 8315
Although the way you are doing this is not the optimal way but if you want to continue then you can do the following.
First instead of registering the click listener in init
block you should define a function
and then pass the values of author and description to that function
. the function defined inside ViewHolder
would look like
fun setClickListener(author: String, description: String) = itemImage.setOnClickListener{
val intent = Intent(view.context, PostActivity::class.java)
intent.putExtra("title",itemTitle.text)
intent.putExtra("source",)
intent.putExtra("author", author)
intent.putExtra("description", description)
view.context.startActivity(intent)
}
Now call this from onBindViewHolder
as
holder.setClickListener(Authors[position], Descriptions[position]);
Also you don't need to build differnt lists for author, description, title etc. Instead define a class
as
data class RecyclerModel(val title: String, val url: String, val author: String, val description: String)
and in your MainActivity
define a list
of this type as
private val recyclerData = mutableListOf<RecyclerModel>()
now in your addToList
function simply do
recyclerData.add(RecyclerModel(title, image, author, description))
Upvotes: 1