• 24-12-2020, 09:11:33
    #1
    Selamun Aleyküm
    Abiler kotlin ile bir uygulama yapıyorum. Konuşmaların listelendiği bölümü yapmaya çalışıyorum fakat No adapter attached; skipping layout hatasını alıyorum ve ekrana hiç bir şey gelmiyor. İnternette baktım fakat kotlin ile ilgili kayda değer bir açıklama bulamadım. Java ile ilgili bir çok açıklama mevcut ama java bilmediğim için pek anlamadım.
    Mesajlaşma bölümünde de aynı şekilde RecyclerView kullandım fakat orada bu şekilde bir hata almadım.
    Kodlarım bu şekilde;
    =====RecyclerView'in getirileceği fragment=====
    class MesajlarFragment : Fragment() {
        lateinit var mAuth: FirebaseAuth
        lateinit var myFragmentView: View
        var tumKonusmalarr: ArrayList<Konusmalar> = ArrayList<Konusmalar>()
        lateinit var myRecyclerView: RecyclerView
        lateinit var myLinearLayoutManager: LinearLayoutManager
        lateinit var myAdapter: KonusmalarRecyclerAdapter
        override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                                  savedInstanceState: Bundle?): View? {
            myFragmentView= inflater.inflate(R.layout.fragment_mesajlar, container, false)
            return myFragmentView
            tumKonusmalariGetir()
        }
    
    
        private fun setupKonusmalarRecylerView() {
            myRecyclerView= myFragmentView.recyclerKonusmalar
            myLinearLayoutManager= LinearLayoutManager(activity,LinearLayoutManager.VERTICAL,false)
            myAdapter= KonusmalarRecyclerAdapter(tumKonusmalarr,this!!.activity!!)
    
            myRecyclerView.layoutManager= myLinearLayoutManager
            myRecyclerView.adapter= myAdapter
        }
        private fun tumKonusmalariGetir() {
            var mRef= FirebaseDatabase.getInstance().reference
            var mUser= FirebaseAuth.getInstance().currentUser
            mRef.child("konusmalar").child(mUser!!.uid).addValueEventListener(object : ValueEventListener{
                override fun onDataChange(snapshot: DataSnapshot) {
                    if (snapshot.getValue() != null){
                        for (konusma in snapshot.children){
                            var  okunanKonusma= konusma.getValue(Konusmalar::class.java)
                            okunanKonusma!!.user_id=konusma.key
                            tumKonusmalarr.add(okunanKonusma!!)
                        }
    
                        setupKonusmalarRecylerView()
    
                    }
                }
    
                override fun onCancelled(error: DatabaseError) {
    
                }
    
            })
        }
    
    }
    ====Adapter====

    class KonusmalarRecyclerAdapter(var tumKonusmalar:ArrayList<Konusmalar>, var myContext: Context):RecyclerView.Adapter<KonusmalarRecyclerAdapter.MyViewHolder>() {
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
    
            var myView=LayoutInflater.from(myContext).inflate(R.layout.tek_satir_konusma_item,parent,false)
            return  MyViewHolder(myView)
        }
        override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
            holder.setData(tumKonusmalar.get(position))
        }
    
        override fun getItemCount(): Int {
            return  tumKonusmalar.size
        }
    
        class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
            var tumLayout = itemView as ConstraintLayout
            var ensonAtilanMesaj= tumLayout.tvSonMesajMessenger
            var mesajZaman= tumLayout.tvMesajZamanMessenger
            var sohbetEdilenUserName= tumLayout.tvUserNameMessenger
    
    
            fun setData(oankiKonusma: Konusmalar){
                ensonAtilanMesaj.text=oankiKonusma.son_mesaj.toString()
                mesajZaman.text=TimeAgo.getTimeAgo(oankiKonusma.time!!.toLong())
    
                sohbetEdilenKullaniciBilgileriniGetir(oankiKonusma.user_id.toString())
    
            }
    
            private fun sohbetEdilenKullaniciBilgileriniGetir(userID: String) {
                FirebaseDatabase.getInstance().getReference().child("users").child(userID).addListenerForSingleValueEvent(object : ValueEventListener{
                    override fun onDataChange(snapshot: DataSnapshot) {
                        if (snapshot.getValue() != null){
                            for (ds in snapshot!!.children){
                                var bulunanKullanici= ds.getValue(Users::class.java)
                                sohbetEdilenUserName.text=snapshot.child("user_name").getValue().toString()
    
                            }
                        }
    
                    }
    
                    override fun onCancelled(error: DatabaseError) {
    
                    }
    
                })
    
            }
    
    
        }
    }
    Bugün sabahladım ama bir türlü çözüme ulaşamadım. Açıkçası kotlin'de yeniyim, internette yapılmış olan açıklamalardan da pek bir şey anlayabildiğim söylenemez. Acaba yardımcı olabilecek yada kodlar içinde hatayı gören yardımcı olabilir mi?
    Şimdiden herkese teşekkür ederim.
  • 24-12-2020, 15:22:54
    #2
    O bir hata değil uygulama ile alakalı bir uyarıdır sizin adapter sınıfınız ile alaklı değil. Burda gelen veriyi kontrol ediniz boş geliyorsa zaten doldurulamaz. Adapter sınıfında veri çekilemez siz yapıyı yanlış kurmuşssunuz. Örnek adapter sınıfını bırakıyorum;

    class PayoutListAdapter(var payouts: List<Payout>, private val itemClick: (Payout) -> Unit) :
        RecyclerView.Adapter<PayoutListAdapter.ViewHolder>() {
    
    
    
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
            val view = LayoutInflater.from(parent.context).inflate(R.layout.item_payout, parent, false)
            return ViewHolder(view, itemClick)
        }
    
    
        override fun onBindViewHolder(holder: ViewHolder, position: Int) {
            holder.bindForecast(payouts[position])
        }
    
    
        override fun getItemCount() = payouts.size
    
    
        class ViewHolder(view: View, private val itemClick: (Payout) -> Unit) :
            RecyclerView.ViewHolder(view) {
    
    
            @SuppressLint("SetTextI18n")
            fun bindForecast(p: Payout) {
                with(p) {
                    val context = itemView.context
                    val v = itemView
                    v.tvPayoutTitle.text = p.title
                    v.tvReqiredRank.text= p.requiredLevel
            
                    v.setOnClickListener { itemClick(this) }
                }
            }
        }
    }
    En üstte adapter değişkeninizi oluşturun

    var payoutListAdapter:PayoutListAdapter?=null
    Bu şekilde kullanın
     override fun onDataLoad(payoutList: List<Payout>) { // bu fonksiyon benim verilerim gelince çalışıyor
            rvPayoutList.apply {
                if(payoutListAdapter==null){
                    payoutListAdapter = PayoutListAdapter(payoutList) {
                   //  bu parantez lambda dır unit metot olarak çalışır geri dönüşü default it dir isterseniz {  gelenveri -> şeklinde değiştirebilirsiniz
                        payoutItemClicked(it) // bu kısım tıklanılan item'ın verilerini içerir burda başka bir metoda gönderiyorum
                    }
                }else{
                    payoutListAdapter!!.payouts = payoutList
                }
    
    
                adapter=payoutListAdapter
    
    
            }
            println(payoutList)
        }
    edit: layout manageri xml kısmında hallediniz
  • 24-12-2020, 19:47:35
    #3
    ilkeryildirim adlı üyeden alıntı: mesajı görüntüle
    O bir hata değil uygulama ile alakalı bir uyarıdır sizin adapter sınıfınız ile alaklı değil. Burda gelen veriyi kontrol ediniz boş geliyorsa zaten doldurulamaz. Adapter sınıfında veri çekilemez siz yapıyı yanlış kurmuşssunuz. Örnek adapter sınıfını bırakıyorum;

    class PayoutListAdapter(var payouts: List<Payout>, private val itemClick: (Payout) -> Unit) :
        RecyclerView.Adapter<PayoutListAdapter.ViewHolder>() {
    
    
    
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
            val view = LayoutInflater.from(parent.context).inflate(R.layout.item_payout, parent, false)
            return ViewHolder(view, itemClick)
        }
    
    
        override fun onBindViewHolder(holder: ViewHolder, position: Int) {
            holder.bindForecast(payouts[position])
        }
    
    
        override fun getItemCount() = payouts.size
    
    
        class ViewHolder(view: View, private val itemClick: (Payout) -> Unit) :
            RecyclerView.ViewHolder(view) {
    
    
            @SuppressLint("SetTextI18n")
            fun bindForecast(p: Payout) {
                with(p) {
                    val context = itemView.context
                    val v = itemView
                    v.tvPayoutTitle.text = p.title
                    v.tvReqiredRank.text= p.requiredLevel
            
                    v.setOnClickListener { itemClick(this) }
                }
            }
        }
    }
    En üstte adapter değişkeninizi oluşturun

    var payoutListAdapter:PayoutListAdapter?=null
    Bu şekilde kullanın
     override fun onDataLoad(payoutList: List<Payout>) { // bu fonksiyon benim verilerim gelince çalışıyor
            rvPayoutList.apply {
                if(payoutListAdapter==null){
                    payoutListAdapter = PayoutListAdapter(payoutList) {
                   //  bu parantez lambda dır unit metot olarak çalışır geri dönüşü default it dir isterseniz {  gelenveri -> şeklinde değiştirebilirsiniz
                        payoutItemClicked(it) // bu kısım tıklanılan item'ın verilerini içerir burda başka bir metoda gönderiyorum
                    }
                }else{
                    payoutListAdapter!!.payouts = payoutList
                }
    
    
                adapter=payoutListAdapter
    
    
            }
            println(payoutList)
        }
    edit: layout manageri xml kısmında hallediniz
    Teşekkür ederim hocam hemen bakıyorum
  • 25-12-2020, 19:06:28
    #4
    Bunun sebebi receylerview ın adapter ini geç setliyor olmanız. Recyclerview ın adapterini hemen setlemeniz lazım. Layout init olurken recyclerview adaptere ihtiyaç duyar bulamaz ise bu hatayı verir. onCreateView içinde hemen boş arraylist ile setAdapter kullanarak setleyin. Asenkron olarak kendi listeniz yüklendikten sonra notifydatasetchanged() ile güncellersiniz. Sorunun kesin çözümü budur.
  • 25-12-2020, 19:08:05
    #5
    sefagurel adlı üyeden alıntı: mesajı görüntüle
    Bunun sebebi receylerview ın adapter ini geç setliyor olmanız. Recyclerview ın adapterini hemen setlemeniz lazım.

    onCreateView içinde hemen boş arraylist ile setleyin. Asenkron olarak kendi listeniz yüklendikten sonra notifydatasetchanged() ile güncellersiniz. Sorunun kesin çözümü budur.
    Teşekkür ederim hocam sağolun. Sorun çözüldü aslında ama logcat'te hala uyarıyı alıyordum dediklerinizi deneyeceğim
  • 27-12-2020, 18:31:46
    #6
    Onu hata olarak görmemelisin. sadece bir uyarı. Bugüne kadar herhangi bir sorunla karsılasmadım.
  • 27-12-2020, 21:54:57
    #7
    yassow42 adlı üyeden alıntı: mesajı görüntüle
    Onu hata olarak görmemelisin. sadece bir uyarı. Bugüne kadar herhangi bir sorunla karsılasmadım.
    Çok teşekkür ederim hocam bilgilendirdiğiniz için.