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