Receive data from Adapter to DetailsActivity? - kotlin

I want to know how I can receive the data from adapter (recyclerview) to DetailsActivity. I tried many times but the images from recyclerview doesn't show in DetailsActivity.
this is my code.
ImageAdapter
class ImageAdapter (private var items:List<Item>, private val context:Context):
RecyclerView.Adapter<ImageAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int):ViewHolder {
return ViewHolder(
LayoutInflater.from(context).inflate(R.layout.item, parent, false)
)
}
override fun getItemCount(): Int {
return items.size
}
override fun onBindViewHolder(holder: ImageAdapter.ViewHolder, position: Int) {
val item = items[position]
Picasso.get().load(item.imageUrl).into(holder.imageView)
holder.imageView.setOnClickListener {
val intent = Intent(context, DetailsActivity::class.java)
intent.putExtra("iImages", item.imageUrl)
context.startActivity(intent)
}
}
class ViewHolder(view:View):RecyclerView.ViewHolder(view) {
val imageView : ImageView = view.findViewById(R.id.imageView)
}
}
DetailsActivity
class DetailsActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_details)
val aImageView = intent.getIntExtra("iImages", 0)
details_image.setImageResource(aImageView)
}
}
RecyclerActivity
class RecyclerActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_recycler)
val storage = FirebaseStorage.getInstance()
val storageRef = storage.reference.child("wallpapers")
val imageList : ArrayList<Item> = ArrayList()
//progressBar.visibility = View.VISIBLE
val listAllTask : Task<ListResult> = storageRef.listAll()
listAllTask.addOnCompleteListener { result ->
val items: List<StorageReference> = result.result!!.items
//add cycle for add image url to list
items.forEachIndexed { index,item ->
item.downloadUrl.addOnSuccessListener {
Log.d("item", "$it")
imageList.add(Item(it.toString()))
}.addOnCompleteListener {
recyclerview.adapter = ImageAdapter(imageList, this)
recyclerview.layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
//progressBar.visibility = View.GONE
}
}
}
}
}
Item
data class Item(
var imageUrl: String
)

The problem is this line:
details_image.setImageResource(aImageView)
You are setting a resource int but what you pass seems to be a url, so instead load the "iImages" value with Picasso for that view
Edit: Replace this:
val aImageView = intent.getIntExtra("iImages", 0)
details_image.setImageResource(aImageView)
with this
val retrievedImageUrl = intent.getIntExtra("iImages", 0)
Picasso.get().load(retrievedImageUrl).into(details_image)

The Answer
val imageView : ImageView = findViewById(R.id.details_image)
Glide.with(this).load(intent.getStringExtra("iImages")).into(imageView)

Related

E/RecyclerView: No adapter attached; skipping layout while getting the data from Google Spreadsheet

I am trying to get the data from the Google Spreadsheet and display it in a recyclerView in Kotlin. But I am getting the error as in the title.
I know there are many questions about the error 'E/RecyclerView: No adapter attached'. I spent hours going through all the posts and made changes to my code. But I couldn't fix the issue as I am not an expert coder.
Following is SalesData.kt
class SalesData : AppCompatActivity() {
private lateinit var binding: ActivitySalesDataBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivitySalesDataBinding.inflate(layoutInflater)
setContentView(binding.root)
val salesList = arrayListOf<SalesDataModel>()
binding.rvSalesData.layoutManager = LinearLayoutManager(applicationContext)
binding.rvSalesData.setHasFixedSize(true)
val adapter = SalesDataRecyclerAdapter(applicationContext,salesList)
binding.rvSalesData.adapter = adapter
val queue = Volley.newRequestQueue(this)
val url = "https://script.google.com/macros/s/fssfsdffdfhfhPPEWVM2FeIH3gZY5kAnb6JVeWpg2Xedfgt443534tdfg43t/exec"
val jsonObjectRequest = object: JsonObjectRequest(Request.Method.GET,url,null,Response.Listener {
val data = it.getJSONArray("items")
for(i in 0 until data.length()){
val salesJasonObject = data.getJSONObject(i)
val salesObject = SalesDataModel(
salesJasonObject.getString("Date"),
salesJasonObject.getString("Branch"),
salesJasonObject.getDouble("NetSale"),
salesJasonObject.getDouble("Profit"),
)
salesList.add(salesObject)
adapter.notifyDataSetChanged()
}
},Response.ErrorListener { }
){
override fun getHeaders(): MutableMap<String, String> {
return super.getHeaders()
}
}
}
}
and this is the adapter class SalesDataRecyclerAdapter.kt
class SalesDataRecyclerAdapter(val context: Context, private val saleDataList:ArrayList<SalesDataModel>)
:RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return MyViewHolder(
SalesDataLayoutBinding.inflate(
LayoutInflater.from(
parent.context
), parent, false
)
)
}
override fun getItemCount(): Int {
return saleDataList.size
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val model = saleDataList[position]
if (holder is MyViewHolder){
holder.binding.tvSales.text = model.salesAmount.toString()
holder.binding.tvBranch.text = model.branch
holder.binding.tvDate.text = model.date
holder.binding.tvProfit.text = model.profit.toString()
}
}
private class MyViewHolder(val binding: SalesDataLayoutBinding) : RecyclerView.ViewHolder(binding.root)
}

how do i update items that change in recyclerview use diffutil?

DiffUtil do not update items recyclerview with the same id and not same the content,
The model has [id : Int and title : String]. I want to the diffUtilCallBack check items with the same id and not same title and update to recyclerview
Please help me fix it
my DiffUtil CallBAck
class DiffCB(
val oldl : ArrayList<Test>,
val newl : ArrayList<Test>
) : DiffUtil.Callback() {
override fun getOldListSize(): Int {
return oldl.size
}
override fun getNewListSize(): Int {
return newl.size
}
override fun areItemsTheSame(oldItemPos: Int, newItemPos: Int): Boolean {
return oldl[oldItemPos].id == newl[newItemPos].id
}
override fun areContentsTheSame(oldItemPos: Int, newItemPos: Int): Boolean {
return oldl[oldItemPos].title.equals(newl[newItemPos].title)
}
}
my Adapter.kt
class TestAdapter(val click: TestClick) :
RecyclerView.Adapter<TestAdapter.TestVH>() {
var list: ArrayList<Test> = ArrayList()
inner class TestVH(val bin: ItemTestBinding) : RecyclerView.ViewHolder(bin.root) {
fun bind(test: Test) {
bin.tvTestId.text = "[id: ${test.id}]"
bin.tvTestTitle.text = test.title
bin.cbTest.isChecked = test.select
bin.cbTest.setOnClickListener {
click.click(test)
}
}
}
fun sumbitData(newl: ArrayList<Test>) {
val diff = DiffCB(this.list, newl)
val diffResult = DiffUtil.calculateDiff(diff)
list.clear()
this.list.addAll(newl)
diffResult.dispatchUpdatesTo(this)
}
override fun getItemCount(): Int {
return list.size
}
override fun onBindViewHolder(holder: TestVH, position: Int) {
holder.bind(list[position])
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TestVH {
return TestVH(ItemTestBinding.inflate(LayoutInflater.from(parent.context),
parent, false))
}
}
my Activity.kt
class TestActivity : AppCompatActivity(), TestClick {
private var list : ArrayList<Test> = ArrayList()
private lateinit var bin : ActivityTestBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
bin = ActivityTestBinding.inflate(layoutInflater)
setContentView(bin.root)
val viewModel = ViewModelProviders.of(this).get(TestViewModel::class.java)
val manager = LinearLayoutManager(this)
bin.rvTest.layoutManager = manager
val adapter = TestAdapter(this)
bin.rvTest.adapter = adapter
//init first data
viewModel.setTests(initData())
viewModel.getTests().observe(this, Observer {
adapter.sumbitData(it as ArrayList<Test>)
})
bin.btnTest.setOnClickListener{
viewModel.setTests(updateData())
}
}
fun updateData() : ArrayList<Test> {
for (i in 2..6) {
var test = Test()
test.id = i
test.title = "title test $i update"
list.add(test)
}
return list
}
fun initData() : ArrayList<Test> {
for (i in 1..3) {
var test = Test()
test.id = i
test.title = "title test $i"
list.add(test)
}
return list
}
override fun click(test: Test) {
Toast.makeText(this, "${test.id} ${test.title}", Toast.LENGTH_SHORT).show()
}
}
it is first data
after update data, items with the same id have not been updated (id 2, 3)

Recyclerview does not display on the screen in kotlin

So I tried to create multi views recyclerview in kotlin, but sadly it did not work.The recyclerview does not display on the screen. It worth to mention that I tried to set the orientation as vertical in my layout files, also added all the dependencies and things needed. Can anyone please help me with that?
My MainActivity.class
#AndroidEntryPoint
class MainActivity : AppCompatActivity() {
lateinit var binding: ActivityMainBinding
lateinit var adapter: NumbersAdapter
lateinit var recyclerView: RecyclerView
var list: List<Nums> = listOf(Nums(1,false))
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
updateAll()
}
fun updateAll(){
binding.recyclerview.apply {
val layoutManager = LinearLayoutManager(this#MainActivity)
adapter = NumbersAdapter(list)
adapter = adapter
}}}
My Adapter
class NumbersAdapter(
var list: List<Nums>,
): RecyclerView.Adapter<RecyclerView.ViewHolder>() {
class RedViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val name = itemView.findViewById<TextView>(R.id.red_number)
fun bindRed(number: Nums) {
name.text = number.nums.toString()
}
}
class OrangeViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val name = itemView.findViewById<TextView>(R.id.orange_number)
fun bindOrange(number: Nums) {
name.text = number.nums.toString()
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
if (viewType == 0) {
val redvView =
LayoutInflater.from(parent.context).inflate(R.layout.red_item, parent, false)
return RedViewHolder(redvView)
}
else {
val orangeView =
LayoutInflater.from(parent.context).inflate(R.layout.orange_item, parent, false)
return OrangeViewHolder(orangeView)
}
}
override fun getItemCount(): Int {
return list.size
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if(getItemViewType(position)==0){
(holder as RedViewHolder).bindRed(list[position])
}
else{
(holder as OrangeViewHolder).bindOrange(list[position])
}
}
override fun getItemViewType(position: Int): Int {
checkItem()
if(list[position].flag)
return 0
return 1
}
fun checkItem(){
for (i in list.indices) {
for (k in i + 1 until list.size) {
if (list[i].nums + list[k].nums == 0) {
list[i].flag = true
list[k].flag = true
}}}}}
in MainActivity.class change code in updateAll() function
fun updateAll(){
binding.recyclerView.apply {
adapter = NumbersAdapter(list)
layoutManager = LinearLayoutManager(this#MainActivity)
}
}

i want to add next page (every page is 10) to my recyclerview but it delet my last page

my recyclerview fragment:
this is the fragment that I set my recycler view , I want when touch the continue button (btn_continue) add the rest of the list, which is actually the next page, to my list when I click the button
But it deletes the previous list and displays the new list
and i use the kotlin coruotine, viewmodel and recyclerview
class AllUnpublishedAdsFragment : Fragment() {
lateinit var unpublishedAdsAdapter: UnpublishedAdsAdapter
var items = ArrayList<M_Ads>()
lateinit var loadMoreItems: ArrayList<M_Ads>
lateinit var scrollListener: RecyclerViewLoadMoreScroll
lateinit var mLayoutManager: RecyclerView.LayoutManager
val page = "1"
var newpage = page.toInt()
var navController: NavController? = null
lateinit var btn_continue: Button
private lateinit var viewModel: MainViewmodels
lateinit var token: String
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_all_unpublished_ads, container,
false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
btn_continue = view.findViewById<Button>(R.id.btn_continueAds)
token = arguments?.getString(TOKEN_KEY).toString()
Log.i("TOKEN", token)
setupViewModel(token, page)
continueAds()
unpublishedAdsAdapter.itemClickListener = { item, position ->
val id = item.id
val bundle_id = Bundle()
bundle_id.putString(ID_KEY, id.toString())
navController = Navigation.findNavController(view)
//view.findNavController().navigate(R.id.action_UnpublishedAds_to_Detail,
bundle_id)
navController!!.navigate(
R.id.action_allUnpublishedAdsFragment_to_adsDetailFragment,
bundle_id
)
}
}
private fun setupViewModel(token: String, page: String) {
LoadingDialog.show(requireContext(), { ld ->
recy_unpublished_ads.layoutManager = LinearLayoutManager(activity)
val decoration = DividerItemDecoration(activity, DividerItemDecoration.VERTICAL)
recy_unpublished_ads.addItemDecoration(decoration)
viewModel = ViewModelProvider(this).get(MainViewmodels::class.java)
unpublishedAdsAdapter = UnpublishedAdsAdapter()
recy_unpublished_ads.adapter = unpublishedAdsAdapter
viewModel.adsListObserve().observe({ lifecycle }, { model ->
items.clear()
items.addAll(model.adsList!!)
unpublishedAdsAdapter.setUpdateData(items)
ld.dismiss()
btn_continue.visibility = View.VISIBLE
})
viewModel.getAdsList(token, page)
})
}
fun continueAds() {
var isTouched=false
btn_continue.setOnClickListener {
isTouched=true
newpage = newpage + 1
Log.i("CONTINUE", newpage.toString())
setupViewModel(token, newpage.toString())
unpublishedAdsAdapter.notifyDataSetChanged()
isTouched=false
}
}
RetrofitInstance class
class RetrofitInstance {
companion object{
fun getRetrofitInstance (): Retrofit{
// val interceptor = HttpLoggingInterceptor()
// interceptor.setLevel(HttpLoggingInterceptor.Level.BODY)
// val client: OkHttpClient = OkHttpClient.Builder().addInterceptor(interceptor).build()
val okHttpClient: OkHttpClient = OkHttpClient.Builder()
.readTimeout(60, TimeUnit.SECONDS)
.connectTimeout(60, TimeUnit.SECONDS)
.build()
return Retrofit.Builder()
.baseUrl(BASEURL)
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient)
.build()
}
}
}
my adapter:
class UnpublishedAdsAdapter : RecyclerView.Adapter<UnpublishedAdsAdapter.MyViewHolder>() {
var items = ArrayList<M_Ads>()
var itemClickListener: ((item: M_Ads, position: Int) -> Unit)? = null
lateinit var mcontext: Context
class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
class LoadingViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
fun setUpdateData(items: ArrayList<M_Ads>) {
this.items = items
notifyDataSetChanged()
}
class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val img_ads = view.findViewById<ImageView>(R.id.img_recy_ads)
val txt_title = view.findViewById<TextView>(R.id.txt_recy_ads_title)
val txt_accountType = view.findViewById<TextView>(R.id.txt_recy_ads_acctype)
fun bind(data: M_Ads) {
txt_title.setText(data.title)
txt_accountType.setText(data.accountType)
if (!data.image1.equals("")) {
Picasso.with(img_ads.context).load(data.image1).into(img_ads)
} else {
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
mcontext = parent.context
return if (viewType == Constant.VIEW_TYPE_ITEM) {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.row_recy_unpublished_ads, parent, false)
MyViewHolder(view)
} else {
val view =
LayoutInflater.from(mcontext).inflate(R.layout.progress_loading, parent, false)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
view.progressbar.indeterminateDrawable.colorFilter =
BlendModeColorFilter(Color.WHITE, BlendMode.SRC_ATOP)
} else {
view.progressbar.indeterminateDrawable.setColorFilter(
Color.WHITE,
PorterDuff.Mode.MULTIPLY
)
}
MyViewHolder(view)
}
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.bind(items.get(position))
handleClick(holder)
}
fun handleClick(holder: UnpublishedAdsAdapter.MyViewHolder) {
holder.itemView.setOnClickListener {
val position = holder.adapterPosition
itemClickListener?.invoke(items.get(position), position)
}
}
override fun getItemCount(): Int {
return items.size
}
my Viewmodel:
class MainViewmodels:ViewModel() {
lateinit var getAds:MutableLiveData<Main_ModelAds>
init {
getAds= MutableLiveData<Main_ModelAds>()
}
fun adsListObserve():MutableLiveData<Main_ModelAds>{
return getAds
}
fun getAdsList(token:String,page:String){
viewModelScope.launch(Dispatchers.IO) {
try {
Log.i("ERRORRES",token + "")
val retrofitInstance=RetrofitInstance.getRetrofitInstance().create(RetrofitService::class.java)
val response=retrofitInstance.unPublishedAdsList(token,page)
getAds.postValue(response)
}catch (ex:Exception){
Log.i("ERRORRES", ex.message.toString() + "")
}
}
}
What you want here is to update the list that you are showing when the user clicks the button.
In this case you should use ListAdapter.
You can refer to this article for implementation:
https://developer.android.com/reference/androidx/recyclerview/widget/ListAdapter

RecyclerView onClick in kotlin

I'm new android learner, I'm trying to make a RecyclerView contains of List of (Stories Title, and Stories images).
When you click on an item in the RecyclerView it should open a new activity called ChildrenStoriesPreview contains of ScrollView which have ImageView to put the Story Image in it and TextView to put the Text of the Story in it.
the problem is that I don't know how to set ocItemClickListener to know which item is clicked and how the new activity will contain information depending on this item? Could you please help me?
here is my Main.kt
class MainChildrenStories : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main_children_stories)
var childrenStoriesArraylist = ArrayList<ChildrenStoriesRecyclerView>()
childrenStoriesArraylist.add(ChildrenStoriesRecyclerView("Story1", R.drawable.pic1))
childrenStoriesArraylist.add(ChildrenStoriesRecyclerView("Story2", R.drawable.pic2))
childrenStoriesArraylist.add(ChildrenStoriesRecyclerView("Story3", R.drawable.pic3))
children_stories_recyclerview.layoutManager = LinearLayoutManager(this, LinearLayout.VERTICAL, false)
val childrenStoriesAdapter = ChildrenStoriesAdapter(childrenStoriesArraylist)
children_stories_recyclerview.adapter = childrenStoriesAdapter
childrenStoriesAdapter.setOnItemClickListener(object : ChildrenStoriesAdapter.ClickListener {
override fun onClick(pos: Int, aView: View) {
//The App Crash here
if (pos == 0){
my_text_view.text = "Story number 1"
my_imageview.setImageResource(R.drawable.pic1)
}else if (pos == 1){
my_text_view.text = "Story number 2"
my_imageview.setImageResource(R.drawable.pic2)
}
val intent = Intent(this#MainChildrenStories, ChildrenStoryPreview::class.java)
startActivity(intent)
}
})
}
}
MyRecyclerView Class
data class ChildrenStoriesRecyclerView(var mStoryName: String, var mStoryImage: Int)
My RecyclerView Adapter Class
class ChildrenStoriesAdapter(var myArrayList: ArrayList<ChildrenStoriesRecyclerView>) :
RecyclerView.Adapter<ChildrenStoriesAdapter.ViewHolder>() {
lateinit var mClickListener: ClickListener
fun setOnItemClickListener(aClickListener: ClickListener) {
mClickListener = aClickListener
}
override fun onCreateViewHolder(p0: ViewGroup, p1: Int): ViewHolder {
val v = LayoutInflater.from(p0.context).inflate(R.layout.children_stories_list, p0, false)
return ViewHolder(v)
}
override fun getItemCount(): Int {
return myArrayList.size
}
override fun onBindViewHolder(p0: ViewHolder, p1: Int) {
var infList = myArrayList[p1]
p0.storyName.text = infList.mStoryName
p0.storyImage.setImageResource(infList.mStoryImage)
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
override fun onClick(v: View) {
mClickListener.onClick(adapterPosition, v)
}
val storyName = itemView.findViewById(R.id.txtStoryName) as TextView
val storyImage = itemView.findViewById(R.id.imageViewChildrenStories) as ImageView
init {
itemView.setOnClickListener(this)
}
}
interface ClickListener {
fun onClick(pos: Int, aView: View)
}
}
My new Activity To show Details of the Story
class ChildrenStoryPreview : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_children_story_preview)
}
}
Pass the Event Listener to Adapter constructor also to viewholder to catch view holder (items) clicks.
class ChildrenStoriesAdapter(var myArrayList: ArrayList<ChildrenStoriesRecyclerView>
var clickListener:MyClickListener?) :
RecyclerView.Adapter<ChildrenStoriesAdapter.ViewHolder>() {
...
override fun onCreateViewHolder(p0: ViewGroup, p1: Int): ViewHolder {
val v = LayoutInflater.from(p0.context).inflate(R.layout.children_stories_list, p0, false)
return ViewHolder(v, clickListener)
}
...
inner class ViewHolder(itemView: View, clickListener:MyClickListener?) :
RecyclerView.ViewHolder(itemView) {
itemView.setOnClickListener { clickListener?.myClickedFun(...) }
...
class ChildrenStoryPreview : AppCompatActivity(), MyClickListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_children_story_preview)
}
override fun myClickedFun(...) {
...
}
}
Later init adapter like
..
val childrenStoriesAdapter = ChildrenStoriesAdapter(childrenStoriesArraylist, this)