Как передавать данные между действиями, которые не привязаны к представлению первого действия

#android #kotlin #android-recyclerview

Вопрос:

У меня есть это приложение, в котором у меня есть вид переработчика, который получает изображения и заголовки новостей. Затем, когда пользователь нажимает на изображение, новость должна открыться и показать изображение, название, а затем автора и описание новости. Дело в том, что автора и описания не было в представлении переработчика, и я хочу добавить их ко второму действию, которое показывает детали новостей. Как я могу это сделать, поскольку данные еще не привязаны к какому-либо представлению и, следовательно, я не могу передать их через намерение (я думаю)?

Это мой адаптер рециркулятора с setOnClickListener, который запускает второе действие:

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

Это второе действие, которое должно содержать дополнительные сведения:

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

Это основное направление деятельности:

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

}
 

Комментарии:

1. Каждая модель, которую вы показываете в своем первом действии, должна иметь какой-то идентификатор, который можно передать на другой экран. Вы не должны пытаться передавать фактические данные пользовательского интерфейса между действиями так, как (я думаю) вы описываете.

Ответ №1:

Хотя то, как вы это делаете, не является оптимальным способом, но если вы хотите продолжить, вы можете сделать следующее.

Сначала вместо регистрации прослушивателя щелчков в init блоке вы должны определить a function , а затем передать ему значения автора и описания function . функция, определенная внутри ViewHolder , будет выглядеть так

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

Теперь вызовите это из onBindViewHolder as

 holder.setClickListener(Authors[position], Descriptions[position]);
 

Кроме того, вам не нужно создавать различные списки для автора, описания, названия и т.д. Вместо этого определите a class как

 data class RecyclerModel(val title: String, val url: String, val author: String, val description: String)
 

и в вашем MainActivity определении a list этого типа как

 private val recyclerData = mutableListOf<RecyclerModel>()
 

теперь в вашей addToList функции просто сделайте

 recyclerData.add(RecyclerModel(title, image, author, description))