I can't view my data from api in recyclerview. Can you help me what is the problem?
MyCode:
Adapter:
class NewsAdapter(private val data: List<AllData>) :
RecyclerView.Adapter<NewsAdapter.MyViewHolder>() {
class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val title = view.findViewById<TextView>(R.id.news_info)
val imageView = view.findViewById<ImageView>(R.id.news_img)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.main_activity_cardview_card_menu, parent, false)
return MyViewHolder(view)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val news:AllData=data[position]
holder.title.text = news.haberler[position].title
Glide.with(holder.imageView.context).load(news.haberler[position].imageUrl).into(holder.imageView)
}
override fun getItemCount(): Int {
return data.size
}
}
activity_main.xml
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/news_recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/view" />
MainActivity:
class MainActivity : AppCompatActivity() {
private val itemList = ArrayList<MenuCardModel>()
private lateinit var menuCardAdapter: MenuCardAdapter
private lateinit var newsAdapter: NewsAdapter
val data = ArrayList<AllData>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
loadNews()
}
private fun loadNews() {
val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
val service = retrofit.create(ApiInterface::class.java)
val call = service.getNews()
call.enqueue(object :Callback<AllData>{
override fun onResponse(
call: Call<AllData>,
response: Response<AllData>
) {
response.body()?.let {
data.add(it)
newsAdapter = NewsAdapter(data)
news_recyclerView.adapter = newsAdapter
}
}
override fun onFailure(call: Call<AllData>, t: Throwable) {
t.printStackTrace()
}
})
}
}
Model :
data class Haberler(
val content: String,
val id: Int,
val imageUrl: String,
val orderNo: Int,
val parentId: Any,
val title: String,
val videoUrl: String
)
AllData :
data class AllData(
val haberler: List<Haberler>,
val istatistik: Istatistik,
val konferans: Konferans,
val kvkk: String,
val liveChat: String,
val pratikBilgiler: List<PratikBilgiler>,
val sgkTv: List<SgkTv>,
val sss: List<Ss>,
val state: Boolean,
val subjects: List<Subject>
)
Hello, I can't view my data from api in recyclerview. Can you help me what is the problem?
Hello, I can't view my data from api in recyclerview. Can you help me what is the problem?
Hello, I can't view my data from api in recyclerview. Can you help me what is the problem?
It looks like you forgot to set layout manager to your recyclerview before you set adapter
There are two ways you can set layout manager
First way by xml
<androidx.recyclerview.widget.RecyclerView
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
...
/>
second way is by code
newsAdapter = NewsAdapter(data)
news_recyclerView.layoutManager = LinearLayoutManager(context) // line which you forgot
news_recyclerView.adapter = newsAdapter
for more understanding about layout managers , you can refer below links
https://developer.android.com/reference/androidx/recyclerview/widget/RecyclerView.LayoutManager
Just add layoutManager this line in RecyclerView as follow:
<androidx.recyclerview.widget.RecyclerView
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
...
/>
You are missing layout manager for recycler view
Related
First of all sorry for my bad English.
I'm trying to receive Data from my self-written Python Backend(REST-API) in my Android APP.
ApiService.kt:
private const val Base_URL = "http://192.168.178.93:5000/api/"
private val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
private val retrofit = Retrofit.Builder()
.addConverterFactory(MoshiConverterFactory.create(moshi))
.baseUrl(Base_URL)
.build()
interface TodoApiService{
#GET("todo")
suspend fun getToDo(): List<ToDo>
}
object ToDoApi{
val retrofitService : TodoApiService by lazy {
retrofit.create(TodoApiService::class.java)
}
}
MainActivityViewModel.kt:
class MainActivityViewModel : ViewModel() {
of the most recent request
private val _status = MutableLiveData<String>()
val status: LiveData<String> = _status
private val _toDo = MutableLiveData<List<ToDo>>()
val toDo: LiveData<List<ToDo>> = _toDo
init {
getToDo()
}
private fun getToDo() {
viewModelScope.launch{
try {
_toDo.value = ToDoApi.retrofitService.getToDo()
_status.value = "Success $_toDo"
}catch (e: Exception){
_status.value = "Failure ${e.message}"
}
}
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
>
<androidx.recyclerview.widget.RecyclerView
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/recycler_view"
tools:listitem="#layout/todo_item"/>
</FrameLayout>
todo_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp">
<TextView
android:id="#+id/text_view_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1"/>
</RelativeLayout>
</androidx.cardview.widget.CardView>
TodoAdapter.kt
class TodoAdapter(private val context: Context, private val Items: List<ToDo>):RecyclerView. Adapter<TodoAdapter.TodoViewHolder>(){
class TodoViewHolder(private val view: View) : RecyclerView.ViewHolder(view){
val textView: TextView = view.findViewById(R.id.text_view_name)
}
override fun getItemCount() = Items.size
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TodoViewHolder {
val adapterLayout = LayoutInflater.from(parent.context)
.inflate(R.layout.todo_item, parent, false)
return TodoViewHolder(adapterLayout)
}
override fun onBindViewHolder(holder: TodoViewHolder, position: Int) {
val ToDo = Items.get(position)
holder.textView.text = context.resources.getString(ToDo.Id.toInt())
}
}
MainActivity.kt:
class MainActivity : AppCompatActivity() {
private val viewModel = MainActivityViewModel()
private lateinit var binding: ActivityMainBinding
private lateinit var linearLayoutManager: LinearLayoutManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
linearLayoutManager = LinearLayoutManager(this)
binding.recyclerView.layoutManager = linearLayoutManager
binding.recyclerView.adapter = TodoAdapter(this, viewModel.toDo.value)
}
}
I know that I need an adapter to connect my LiveData to my recyclerView. But I'm not able to implement it right. Android studio tells me I cant use my MutableLiveData<List> for my Adapter that just only needs a normal List(Required: List Found: List?. I cant Cast cause the data could be null.
Your use of LiveData is incorrect. You use it as a simple variable, passing its current value (which is null) to the adapter.
LiveData is intended for data stream and need to be observed.
I like to add a setter for the data on the Adapter class:
fun setData(data: List<ToDo>) {
Items = data
notifyDataSetChanged()
}
And in the Activity, observe the ViewModel's live data and update the adapter when new data arrives:
class MainActivity : AppCompatActivity() {
private lateinit var adapter: TodoAdapter
override fun onCreate(savedInstanceState: Bundle?) {
...
adapter = TodoAdapter(this)
viewModel.todo.observe(this, { todos ->
adapter.setData(todos)
}
}
...
}
Now when you set value to your LiveData in the ViewModel, the adapter will be notified.
This is because you are sending a possible nullable list from the activity to the Adapter. You must do something like this:
binding.recyclerView.adapter = TodoAdapter(this, viewModel.toDo?.value ?: listOf())
I have two activity and each activity has recyclerview, I have nested json.I want when user tap first activity recyclerview then they goes to next activity and show the recyclerview.Better understanding please follow the json link and code.
Json Link
: https://run.mocky.io/v3/8c3f6be2-a53f-47da-838c-72e603af844d
CropData.kt
data class CropData(
#SerializedName("cropImage")
val cropImage: String,
#SerializedName("cropName")
val cropName: String,
#SerializedName("cropTime")
val cropTime: String,
#SerializedName("cropDetails")
val cropDetails: String,
#SerializedName("cropProcess")
val cropProcess: String,
#SerializedName("cropType")
val cropType: String,
#SerializedName("cropFertilizer")
val cropFertilizer: List<CropFertilizer>
)
CropFertilizer.kt
data class CropFertilizer(
#SerializedName("fertilizerName")
val fertilizerName: String,
#SerializedName("fertilizerFirst")
val fertilizerFirst: String,
#SerializedName("fertilizerSecond")
val fertilizerSecond: String,
#SerializedName("fertilizerThird")
val fertilizerThird: String
)
CropActivity.kt
class CropActivity : AppCompatActivity(), CropOnItemClickListener {
private lateinit var viewModel: CropActivityViewModel
private val cropAdapter by lazy { CropAdapter(this) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_crop)
val repository = Repository()
val viewModelFactory = CropActivityViewModelFactory(repository)
viewModel = ViewModelProvider(this, viewModelFactory).get(CropActivityViewModel::class.java)
viewModel.getCropData()
viewModel.cropResponse.observe(this, Observer { response ->
cropAdapter.setData(response)
Log.d("dCrop", response.toString())
})
setUpCrops()
}
private fun setUpCrops() {
crop_recyclerview.layoutManager = LinearLayoutManager(
this,
LinearLayoutManager.VERTICAL, false
)
crop_recyclerview.setHasFixedSize(true)
crop_recyclerview.adapter = cropAdapter
}
override fun onClick(item: CropData, position: Int) {
val intent = Intent(this, CropDetailsActivity::class.java)
intent.putExtra("name", item.cropName)
intent.putExtra("image", item.cropImage)
intent.putExtra("intro", item.cropDetails)
intent.putExtra("process", item.cropProcess)
intent.putExtra("type", item.cropType)
intent.putExtra("time", item.cropTime)
startActivity(intent)
}
}
CropAdapter.kt
class CropAdapter(private val cropOnItemClickListener: CropOnItemClickListener) :
RecyclerView.Adapter<CropAdapter.ViewHolder>() {
private var cropList = emptyList<CropData>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.crop_row,parent,false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.itemView.crop_name.text = cropList[position].cropName
holder.itemView.crop_details.text = cropList[position].cropDetails
holder.itemView.crop_time.text = cropList[position].cropTime
holder.itemView.setOnClickListener{
cropOnItemClickListener.onClick(cropList[position],position)
}
}
override fun getItemCount(): Int {
return cropList.size
}
fun setData(newList: List<CropData>){
notifyDataSetChanged()
cropList = newList
notifyDataSetChanged()
}
class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView)
}
CropDetailsActivity.kt
class CropDetailsActivity : AppCompatActivity() {
private lateinit var viewModel: CropDetailsActivityViewModel
private val fertlizerAdapter by lazy { FertilizerAdapter() }
private val cropFertilizerAdapter by lazy { FertilizerAdapter() }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_crop_details)
val bundle:Bundle? = intent.extras
crop_details_name.text = bundle!!.getString("name")
val i: String = bundle!!.getString("intro")
crop_details_intro.text = i
Glide.with(this).load(bundle.getString("image")).into(crop_details_image);
val j: String = bundle!!.getString("process")
crop_details_process.text = j
crop_details_time.text = bundle!!.getString("time")
crop_details_type.text = bundle!!.getString("type")
val repository = Repository()
val viewModelFactory = CropDetailsActivityViewModelFactory(repository)
viewModel = ViewModelProvider(this, viewModelFactory).get(CropDetailsActivityViewModel::class.java)
viewModel.getFertilizer()
viewModel.fResponse.observe(this, Observer {
cropFertilizerAdapter.setData(it)
})
crop_details_recyclerview.layoutManager = LinearLayoutManager(
this,
LinearLayoutManager.VERTICAL, false
)
crop_details_recyclerview.setHasFixedSize(true)
crop_details_recyclerview.adapter = cropFertilizerAdapter
}
}
Better understanding see the image
[1]: https://i.stack.imgur.com/BtPqe.jpg
I want to show CropFertilizer list in CropDetailsActivity.How can i do this?
It is a note taking app. I am using Cloud Firestore to store data. Data got added into database but recycler view is not showing anything. Below are the code snippets.
My Data Model Class:
class Notes {
var id:String?= null
var title: String? = null
var description: String? = null
var created: Timestamp? =null
constructor() {}
constructor(id:String,title: String?, description:String?,created:Timestamp?) {
this.id=id
this.title = title
this.description=description
this.created=created
}
}
AddNotesActivity
class AddNoteActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_add_note)
btn_add_note.setOnClickListener{
val noteTitle = note_title.text.toString()
val noteDescription =note_description.text.toString()
if(noteTitle.isNotEmpty() && noteDescription.isNotEmpty()){
addNotes(noteTitle,noteDescription)
Toast.makeText(this,"note added successfully",Toast.LENGTH_SHORT).show()
onBackPressed()
}
}
}
private fun addNotes(title:String, description:String){
val currentUserId = FirebaseAuth.getInstance().currentUser!!.uid
var note = Notes(currentUserId,title,description, Timestamp(Date()))
FirebaseFirestore.getInstance().collection("notes").add(note).addOnSuccessListener {
Log.i("AddNoteActivity","Note added")
}
}
}
NotesActivity(showing recyclerview):
class NotesActivity : AppCompatActivity() {
lateinit var notesAdapter: NotesAdapter
lateinit var recyclerView: RecyclerView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_notes)
recyclerView = findViewById(R.id.rv_notes)
setUpRecyclerView()
floating_btn.setOnClickListener {
startActivity(Intent(this, AddNoteActivity::class.java))
}
}
private fun setUpRecyclerView() {
val query:Query= FirebaseFirestore.getInstance().collection("notes").whereEqualTo("id",FirebaseAuth.getInstance().currentUser!!.uid)
val options:FirestoreRecyclerOptions<Notes> = FirestoreRecyclerOptions.Builder<Notes>().setQuery(query,Notes::class.java).build()
notesAdapter = NotesAdapter(options)
recyclerView.adapter = notesAdapter
notesAdapter!!.startListening()
}
}
Adapter class:
class NotesAdapter(options:FirestoreRecyclerOptions<Notes>):FirestoreRecyclerAdapter<Notes,NotesAdapter.MyViewHolder>(options) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NotesAdapter.MyViewHolder {
val itemView= LayoutInflater.from(parent.context).inflate(R.layout.each_note_view,parent,false)
return MyViewHolder(itemView)
}
override fun onBindViewHolder(holder: MyViewHolder, p1: Int, NotesModel: Notes) {
holder.title.text = NotesModel.title
holder.description.text= NotesModel.description
val date=DateFormat.getDateInstance(DateFormat.MEDIUM).format(NotesModel.created)
holder.date.text = date.toString()
}
class MyViewHolder(itemView: View): RecyclerView.ViewHolder(itemView){
val title : TextView = itemView.title_text
val description: TextView =itemView.description_text
val date : TextView =itemView.date_created
}
}
But when getting data from querysnapshot, logcat is showing perfect data from firestore database:
val query = FirebaseFirestore.getInstance().collection("notes").whereEqualTo("id", FirebaseAuth.getInstance().currentUser!!.uid).get().addOnSuccessListener {
val doc = it.documents
for (i in doc) {
Log.i("NotesActivity", i.data.toString())
}
}
Logcat: {created=Timestamp(seconds=1611116973, nanoseconds=14000000),
description=day, id=wLxCTMLGZpaWNs1b8Uhf3HoRUgz2, title=go}
I spend two days on this, but not getting any solution. I would be thankful if anybody can solve the issue.
Below is XML file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_notes"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="7"
/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/floating_btn"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_marginEnd="8dp"
android:backgroundTint="#color/light_blue"
android:src="#drawable/floating_btn"/>
hello guys I am using a gson api with a Recyclerview and I got this error with the adapter and it says that the
expression 'myAdapter' of type 'myAdapter' cannot be invoked as a function. the function 'invoked' is not found
and when I run the code without the data it gives me this error:
lateinit property myAdapter has not been initialized
my activities and classes
private val datalist: MutableList<Sura> = mutableListOf()
private lateinit var myAdapter: MyAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_quran_a_p_i)
myAdapter = myAdapter(datalist) // here is the error
apiQuranRecyclerView.layoutManager = LinearLayoutManager(this)
apiQuranRecyclerView.addItemDecoration(DividerItemDecoration(this, OrientationHelper.VERTICAL))
apiQuranRecyclerView.adapter = myAdapter
AndroidNetworking.initialize(this)
AndroidNetworking.get("http://api.islamhouse.com/v1/mykey/quran/get-category/462298/ar/json/")
.build()
.getAsObject(Surasnames::class.java, object : ParsedRequestListener<Surasnames>{
override fun onResponse(response: Surasnames) {
datalist.addAll(response.suras)
myAdapter.notifyDataSetChanged()
}
override fun onError(anError: ANError?) {
}
})
}
my Adapter
class MyAdapter (private val datalist: MutableList<Sura>): RecyclerView.Adapter<myHolder>() {
private lateinit var context: Context
override fun onCreateViewHolder(parent: ViewGroup, p1: Int): myHolder {
context = parent.context
return myHolder(LayoutInflater.from(context).inflate(R.layout.api_quran_view, parent, false))
}
override fun getItemCount(): Int = datalist.size
override fun onBindViewHolder(holder: myHolder, position: Int) {
val data = datalist[position]
val apisuraname = holder.itemView.apiSuraNames
val surasnames = "${data.id} ${data.title}"
apisuraname.text = surasnames
holder.itemView.setOnClickListener {
Toast.makeText(context, surasnames, Toast.LENGTH_SHORT).show()
}
}
my Holder
class myHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
}
my Models
data class Sura(
#SerializedName("add_date")
val addDate: Int,
#SerializedName("api_url")
val apiUrl: String,
#SerializedName("id")
val id: Int,
#SerializedName("title")
val title: String,
#SerializedName("type")
val type: String
)
the second one
data class Surasnames(
#SerializedName("add_date")
val addDate: Int,
#SerializedName("description")
val description: String,
#SerializedName("id")
val id: Int,
#SerializedName("locales")
val locales: List<Any>,
#SerializedName("suras")
val suras: List<Sura>,
#SerializedName("title")
val title: String)
thanks in advance
You need to call the constructor. Change the line
myAdapter = myAdapter(datalist)
to
myAdapter = MyAdapter(datalist)
I'm trying to make an app that shows id and title and whenever some user is clicked, it should go to next activity and show id, userId, title, body, all this coming from implementing REST API from https://jsonplaceholder.typicode.com/post.
I know I have to past it with the intent, but do not know quite how to use it
this is the MainActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(toolbar)
val retrofit= Retrofit.Builder()
.baseUrl("https://jsonplaceholder.typicode.com")
.addConverterFactory(create())
.build()
val api = retrofit.create(ApiService:: class.java)
api.fetchAllPosts().enqueue(object : Callback<List<Post>> {
override fun onResponse(call: Call<List<Post>>, response: Response<List<Post>>) {
showData(response.body()!!)
Log.d("jv", "onResponse")
}
override fun onFailure(call: Call<List<Post>>, t: Throwable) {
Log.d("jv", "onFailure")
}
})
}
private fun showData(posts: List<Post>) {
recyclerView.apply {
layoutManager = LinearLayoutManager(this#MainActivity)
adapter = PostsAdapter(posts)
}
}
}
this is the adapter
class PostsAdapter(private val posts: List<Post>) : RecyclerView.Adapter<PostsAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.post_row, parent, false)
return ViewHolder(view)
}
override fun getItemCount() = posts.size
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.userId.text= "Userid:" + posts[position].userId.toString()
holder.id1.text= "id:" + posts[position].id.toString()
holder.title.text= "Title:" + posts[position].title
holder.body.text= "Body:" + posts[position].body
}
class ViewHolder (itemView:View): RecyclerView.ViewHolder(itemView){
val userId: TextView = itemView.userid
val id1: TextView = itemView.id1
val title: TextView = itemView.title
val body: TextView = itemView.body
}
}
this is the post_row layout
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/photo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="16dp"
android:src="#drawable/ic_check_circle_black_24dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent">
</ImageView>
<TextView
android:id="#+id/id1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp"
android:textColor="#000"
android:textSize="32sp"
app:layout_constraintBottom_toTopOf="#+id/userid"
app:layout_constraintLeft_toRightOf="#+id/photo"
app:layout_constraintTop_toTopOf="parent"
tools:text="1" />
<TextView
android:id="#+id/userid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp"
android:textColor="#000"
android:textSize="32sp"
app:layout_constraintBottom_toTopOf="#+id/title"
app:layout_constraintLeft_toRightOf="#+id/photo"
app:layout_constraintTop_toBottomOf="#+id/id1"
tools:text="1" />
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp"
android:textColor="#000"
android:textSize="32sp"
app:layout_constraintBottom_toTopOf="#+id/body"
app:layout_constraintLeft_toRightOf="#+id/photo"
app:layout_constraintTop_toBottomOf="#+id/userid"
tools:text="JV" />
<TextView
android:id="#+id/body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp"
android:textColor="#000"
android:textSize="32sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="#+id/photo"
app:layout_constraintTop_toBottomOf="#+id/title"
tools:text="JV" />
</androidx.constraintlayout.widget.ConstraintLayout>
You can pass the Post object to the next activity as a Serializable as following.
• At the first step, the Post class should implement Serializable interface:
class Post : Serializable {
// ...
}
• Second step: When the user clicks on each item, put the related Post object to the Intent extras:
val intent = Intent(applicationContext, NextActivity::class.java)
intent.putExtra("post", post)
startActivity(intent)
• Third step: In onCreate of NextActivity, get the object from Intent extras:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val post = intent.getSerializableExtra("post") as Post
// ...
}
* EDIT
I have changed your code to listen to the RecyclerView item clicks. In this way, some changes happened to MainActivity and PostsAdapter classes as well as adding OnRecyclerViewItemClickListener. Notice that Post class should implement Serializable.
MainActivity.kt
class MainActivity : AppCompatActivity(), OnRecyclerViewItemClickListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(toolbar)
val retrofit = Retrofit.Builder()
.baseUrl("https://jsonplaceholder.typicode.com")
.addConverterFactory(create())
.build()
val api = retrofit.create(ApiService::class.java)
api.fetchAllPosts().enqueue(object : Callback<List<Post>> {
override fun onResponse(call: Call<List<Post>>, response: Response<List<Post>>) {
showData(response.body()!!)
Log.d("jv", "onResponse")
}
override fun onFailure(call: Call<List<Post>>, t: Throwable) {
Log.d("jv", "onFailure")
}
})
}
override fun onItemClick(post: Post) {
val intent = Intent(applicationContext, NextActivity::class.java)
intent.putExtra("post", post)
startActivity(intent)
}
private fun showData(posts: List<Post>) {
recyclerView.apply {
layoutManager = LinearLayoutManager(this#MainActivity)
adapter = PostsAdapter(posts, this#MainActivity)
}
}
}
PostsAdapter.kt
class PostsAdapter(
private val posts: List<Post>,
private val itemClickListener: OnRecyclerViewItemClickListener
) : RecyclerView.Adapter<PostsAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.post_row, parent, false)
return ViewHolder(view)
}
override fun getItemCount() = posts.size
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.userId.text = "Userid:" + posts[position].userId.toString()
holder.id1.text = "id:" + posts[position].id.toString()
holder.title.text = "Title:" + posts[position].title
holder.body.text = "Body:" + posts[position].body
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
init {
itemView.setOnClickListener {
itemClickListener.onItemClick(posts[adapterPosition])
}
}
val userId: TextView = itemView.userid
val id1: TextView = itemView.id1
val title: TextView = itemView.title
val body: TextView = itemView.body
}
}
OnRecyclerViewItemClickListener.kt
interface OnRecyclerViewItemClickListener {
fun onItemClick(post: Post)
}
Post.kt
import com.google.gson.annotations.SerializedName
import java.io.Serializable
data class Post(
#SerializedName("userId") val userId: Int = 0,
#SerializedName("id") val id: Int = 0,
#SerializedName("title") val title: String? = null,
#SerializedName("body") val body: String? = null
) : Serializable
NextActivity.kt
class NextActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_next)
val post = intent.getSerializableExtra("post") as Post
// do whatever you want with post!
}
}
To pass an object from one activity to another, your class Post should implement either Serializable or Parcelable interfaces.
data class Post(val title: String, ... ): Serializable
Then you can put object inside the intent. In your RecyclerAdapter
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
...
holder.body.text= "Body:" + posts[position].body
holder.setOnClickListener {
val intent = Intent(holder.context, ActivityYouArePassingTo::class.java)
intent.putExtra("Post", posts[position])
startActivity(intent)
}
}
In the activity that you are navigating to (here ActivityYouArePassingTo)
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
...
// Here is the post from previous activity
val post = intent.getSerializableExtra("Post") as Post
}