dazai
dazai

Reputation: 716

How to pass data between activities that isn't bound to the first activity's view

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

Answers (1)

mightyWOZ
mightyWOZ

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

Related Questions