How to get the id in case no id in the layout - android-studio

I have faced the problem of my application always show keep stopping. It show me the problem is not been initialized. I have try insert findViewbyId for mListener but it say i cannot insert id in constraint layout so mean this way cannot be used. Can somebody help me? Thank for your help
Below are my original code which problem out :
package com.example.assignment_mad
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.imageview.ShapeableImageView
class NotificationAdapter(private val companysList:ArrayList<Company>):RecyclerView.Adapter<NotificationAdapter.MyViewHolder>() {
private lateinit var mListener:onItemClickListener
interface onItemClickListener{
fun onItemClick(position: Int)
}
fun setOnItemClickListener(listener: onItemClickListener){
mListener=listener
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val itemView=LayoutInflater.from(parent.context).inflate(R.layout.list_item,parent,false)
return MyViewHolder(itemView,mListener)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val currentItem=companysList[position]
holder.titleImage.setImageResource(currentItem.titleImage)
holder.tvHeading.text=currentItem.heading
}
override fun getItemCount(): Int {
return companysList.size
}
//to insert the post detail
class MyViewHolder(itemView: View,listener: onItemClickListener):RecyclerView.ViewHolder(itemView){
val titleImage:ShapeableImageView=itemView.findViewById(R.id.title_image)
val tvHeading: TextView =itemView.findViewById(R.id.tvHeading)
init {
itemView.setOnClickListener{
listener.onItemClick(adapterPosition)
}
}
}
}
The list_item xml :
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_margin="8dp">
<com.google.android.material.imageview.ShapeableImageView
android:layout_width="80dp"
android:layout_height="80dp"
android:id="#+id/title_image"
android:scaleType="centerCrop"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:shapeAppearanceOverlay="#style/RoundCorner"
android:src="#drawable/company_logo_1"/>
<TextView
android:id="#+id/tvHeading"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textColor="#color/black"
android:text="Candidate Biden Called Saudi Arable a Pareft eaft."
android:textSize="16dp"
android:textStyle="bold"
android:layout_marginStart="16dp"
android:layout_marginEnd="32dp"
android:layout_marginTop="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/title_image"
app:layout_constraintTop_toTopOf="parent"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_margin="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/title_image"
android:background="#color/underline"/>
</androidx.constraintlayout.widget.ConstraintLayout>
The problem showing :
kotlin.UninitializedPropertyAccessException: lateinit property mListener has not been initialized
at com.example.assignment_mad.NotificationAdapter.onCreateViewHolder(Notificatiion_Adapter.kt:25)
at com.example.assignment_mad.NotificationAdapter.onCreateViewHolder(Notificatiion_Adapter.kt:10)

Add the Nullable check for onItemClickListener type of variable will solve your problem.
package com.example.assignment_mad
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.imageview.ShapeableImageView
class NotificationAdapter(private val companysList:ArrayList<Company>):RecyclerView.Adapter<NotificationAdapter.MyViewHolder>() {
private var mListener:onItemClickListener?=null
interface onItemClickListener{
fun onItemClick(position: Int)
}
fun setOnItemClickListener(listener: onItemClickListener){
mListener=listener
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val itemView=LayoutInflater.from(parent.context).inflate(R.layout.list_item,parent,false)
return MyViewHolder(itemView,mListener)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val currentItem=companysList[position]
holder.titleImage.setImageResource(currentItem.titleImage)
holder.tvHeading.text=currentItem.heading
}
override fun getItemCount(): Int {
return companysList.size
}
//to insert the post detail
class MyViewHolder(itemView: View,listener: onItemClickListener?):RecyclerView.ViewHolder(itemView){
val titleImage:ShapeableImageView=itemView.findViewById(R.id.title_image)
val tvHeading: TextView =itemView.findViewById(R.id.tvHeading)
init {
itemView.setOnClickListener{
listener?.onItemClick(adapterPosition)
}
}
}
}

Your problem is you are not initilizing the mListener properly
kotlin.UninitializedPropertyAccessException: lateinit property mListener has not been initialized at com.example.assignment_mad.NotificationAdapter.onCreateViewHolder(Notificatiion_Adapter.kt:25) at com.example.assignment_mad.NotificationAdapter.onCreateViewHolder(Notificatiion_Adapter.kt:10)
My solution is to pass the listener in the adapter constructor
class NotificationAdapter(
private val companysList:ArrayList<Company>,
private val listener:onItemClickListener
){
// delete
private var mListener:onItemClickListener?=null
// and
fun setOnItemClickListener(listener: onItemClickListener){
mListener=listener
}
}
use it in activity/fragment
adapter = NotificationAdapter(list, object: NotificationAdapter.onItemClickListener{
override fun onItemClick(position:Int){
}
})

Related

Saving RecyclerView state in a fragment when exiting it

I am trying to make a app that sends messages to a recyclerView from fragment to another using a navgraph, but whenever I go back to my previous fragment to add a new message I lose the data of my recyclerView, and does not pile up.
---This is the kotlin code for the first fragment:
package com.example.passingdata
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.EditText
import androidx.navigation.Navigation
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"
class Fragment_A : Fragment() {
// TODO: Rename and change types of parameters
private var param1: String? = null
private var param2: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment__a, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val messageET = view.findViewById<EditText>(R.id.ETmessageTaker)
val enterBTN = view.findViewById<Button>(R.id.BTNenter)
enterBTN.setOnClickListener{
val action = Fragment_ADirections.actionFragmentAToFragmentB(messageET.text.toString())
Navigation.findNavController(view).navigate(action)
}
}
companion object {
fun newInstance(param1: String, param2: String) =
Fragment_A().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
putString(ARG_PARAM2, param2)
}
}
}
}
---XML code for first fragment:
<?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="match_parent"
tools:context=".Fragment_A">
<EditText
android:id="#+id/ETmessageTaker"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:ems="10"
android:hint="Message"
android:inputType="textPersonName"
android:minHeight="48dp"
android:textSize="30sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/BTNenter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:text="Enter"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/ETmessageTaker" />
</androidx.constraintlayout.widget.ConstraintLayout>
---Kotlin code for second fragment :
package com.example.passingdata
import android.content.ContentValues.TAG
import android.os.Bundle
import android.os.Parcelable
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.navigation.Navigation
import androidx.navigation.fragment.navArgs
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.passingdata.databinding.FragmentBBinding
import messageAdapter
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"
var state: Parcelable? = null
class Fragment_B : Fragment() {
// TODO: Rename and change types of parameters
private var param1: String? = null
private var param2: String? = null
private val args:Fragment_BArgs by navArgs()
private var _binding: FragmentBBinding? = null
private val binding get() = _binding!!
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentBBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val eachMessage = args.messageRecieved
//putting words in TV
binding.TVNewMessage.text = eachMessage
//putting words in RV
val messageList = mutableListOf(
message(eachMessage)
)
val adapter = messageAdapter(messageList)
binding.RVMessages.adapter = adapter
binding.RVMessages.layoutManager = LinearLayoutManager(context)
binding.BTNBack.setOnClickListener {
Navigation.findNavController(view).navigate(R.id.action_fragment_B_to_fragment_A)
}
}
companion object {
fun newInstance(param1: String, param2: String) =
Fragment_B().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
putString(ARG_PARAM2, param2)
}
}
}
override fun onResume() {
super.onResume()
Log.d(TAG, "onResume Called")
state = binding.RVMessages.layoutManager?.onSaveInstanceState();
}
override fun onPause() {
super.onPause()
Log.d(TAG, "onPause Called")
state = binding.RVMessages.layoutManager?.onSaveInstanceState();
}
override fun onStop() {
super.onStop()
Log.d(TAG, "onStop Called")
state = binding.RVMessages.layoutManager?.onSaveInstanceState();
}
override fun onDestroy() {
super.onDestroy()
Log.d(TAG, "onDestroy Called")
_binding = null
}
}
---XML code for second fragment:
<?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="match_parent"
tools:context=".Fragment_B">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/RV_messages"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginBottom="20dp"
app:layout_constraintBottom_toTopOf="#+id/TV_newMessage"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/TV_newMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="60dp"
android:text="TextView"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="#+id/BTN_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:layout_marginRight="10dp"
android:text="Back"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<Button
android:id="#+id/BTN_save"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:text="Save"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Someone suggested I override the 3 states and save them like this, but it did not work.
I even tried using SharedPrefrences but it gives me a error saying, "Unresolved reference: getSharedPrefrences".
override fun onResume() {
super.onResume()
Log.d(TAG, "onResume Called")
state = binding.RVMessages.layoutManager?.onSaveInstanceState();
}
override fun onPause() {
super.onPause()
Log.d(TAG, "onPause Called")
state = binding.RVMessages.layoutManager?.onSaveInstanceState();
}
override fun onStop() {
super.onStop()
Log.d(TAG, "onStop Called")
state = binding.RVMessages.layoutManager?.onSaveInstanceState();
}

E/RecyclerView: No adapter attached; skipping layout. Recyclerlist can't be viewed. Output get crashed

Its saying adapter is not attached. I am new to kotlin. So I don't know where does it go wrong.
RestaurantModel.kt
package com.example.foodtogo.model
import android.os.Parcel
import android.os.Parcelable
import java.io.Serializable
class RestaurantModel(val name:String?, val address:String?, val delivery_charge: Int, val image: String?, val open: String?,
var menus: List<Menus?>?): Serializable {}
class Menus(val name:String?, val price: Float, val url:String?, var totalInCart: Int):Serializable {}
RestaurantMainActivity.kt
import android.content.Context
import android.os.Bundle
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.foodtogo.databinding.ActivityRestaurantMainBinding
import com.example.foodtogo.model.RestaurantModel
import com.example.foodtogo.view.RestaurantListAdapter
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.database.*
import com.google.firebase.database.ktx.database
import com.google.firebase.ktx.Firebase
import android.content.Intent as Intent
class RestaurantMainActivity : AppCompatActivity(),RestaurantListAdapter.ValueEventListener {
private lateinit var binding: ActivityRestaurantMainBinding
private lateinit var firebaseAuth: FirebaseAuth
private lateinit var database: FirebaseDatabase
private lateinit var reference: DatabaseReference
private lateinit var restaurantList: ArrayList<RestaurantModel>
//var adapter: RestaurantListAdapter?=null
//private lateinit var restaurantList: MutableList<RestaurantModel?>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityRestaurantMainBinding.inflate(layoutInflater)
setContentView(binding.root)
firebaseAuth = FirebaseAuth.getInstance()
database = FirebaseDatabase.getInstance()
reference = database.reference
Log.e("AKSA", "TEST1")
binding.recyclerViewRestaurant.layoutManager = LinearLayoutManager(this)
Log.e("AKSA", "TEST")
restaurantList = arrayListOf<RestaurantModel>()
getRestaurantData()
Log.e("AKSA", "TEST3")
}
override fun Context.onItemClick(restaurantModel: RestaurantModel) {
val intent = Intent(applicationContext,RestaurantMenuActivity::class.java)
intent.putExtra("RestaurantModel", restaurantModel)
startActivity(intent)
Log.d("AKSA", "MESSAGE")
}
private fun getRestaurantData(){
val db = Firebase.database.reference
val restaurantModelRef = db.child("RestaurantModel")
restaurantModelRef.get().addOnCompleteListener {
if (it.isSuccessful) {
val snapshot = it.result
for (restaurant in snapshot.children) {
Log.d("AKSA", "T4")
val restaurantModel = restaurant.child("RestaurantModel").getValue(RestaurantModel::class.java)
Log.d("AKSA", restaurantModel?.address.toString())
restaurantList.add(restaurantModel!!)
}
val adapter = RestaurantListAdapter(restaurantList, getApplicationContext())
binding.recyclerViewRestaurant.adapter = adapter
adapter.notifyDataSetChanged()
} } }
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menubar, menu)
return super.onCreateOptionsMenu(menu)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.home_menu -> {
val intent = Intent(this, ViewOrderActivity::class.java)
startActivity(intent)
}
R.id.signout_menu -> {
firebaseAuth.signOut()
val intent = Intent(this, LOGIN::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
startActivity(intent)
finish()
}
}
return super.onOptionsItemSelected(item)
}
}
activity_restaurant_main.xml
<?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="match_parent"
android:background="#color/white"
tools:context=".RestaurantMainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerViewRestaurant"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:layout_marginEnd="1dp"
android:layout_marginBottom="4dp"
android:clipToPadding="false"
android:paddingBottom="2dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"
tools:listitem="#layout/recycler_restaurantlist"
tools:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout>
ResaturantListAdapter.kt
import android.content.Context
import android.content.Intent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.example.foodtogo.R
import com.example.foodtogo.RestaurantMenuActivity
import com.example.foodtogo.model.RestaurantModel
class RestaurantListAdapter(val restaurantList: ArrayList<RestaurantModel>, val clickListener: Context):
RecyclerView.Adapter<RestaurantListAdapter.MyViewHolder>() {
//private lateinit var database: FirebaseDatabase
//private lateinit var reference:DatabaseReference
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): RestaurantListAdapter.MyViewHolder {
val view: View = LayoutInflater.from(parent.context).inflate(R.layout.recycler_restaurantlist,parent,false)
return MyViewHolder(view)
}
override fun onBindViewHolder(holder: RestaurantListAdapter.MyViewHolder, position: Int) {
holder.bind(restaurantList.get(position))
holder.itemView.setOnClickListener{
clickListener.onItemClick(restaurantList.get(position))
}
}
override fun getItemCount(): Int {
return restaurantList.size
}
inner class MyViewHolder(view: View):RecyclerView.ViewHolder(view){
val thumbImage: ImageView =view.findViewById(R.id.thumbImage)
val restaurantName: TextView =view.findViewById(R.id.restaurantName)
val restaurantAddress:TextView=view.findViewById(R.id.restaurantAddress)
val restaurantHours:TextView=view.findViewById(R.id.restaurantHours)
fun bind(restaurantModel: RestaurantModel?){
restaurantName.text=restaurantModel?.name
restaurantAddress.text="Address: "+restaurantModel?.address
restaurantHours.text="Open: "+restaurantModel?.open
Glide.with(this.thumbImage).load(restaurantModel?.image).centerCrop().placeholder(R.drawable.ic_launcher_background).into(thumbImage)
}
}
interface ValueEventListener {
// fun onItemClick(restaurantModel: RestaurantModel)
fun Context.onItemClick(restaurantModel: RestaurantModel)
}
}
private fun Context.onItemClick(restaurantModel: RestaurantModel) {
val intent = Intent(applicationContext, RestaurantMenuActivity::class.java)
intent.putExtra("RestaurantModel", restaurantModel)
startActivity(intent)
}
recycler_restaurantlist.xml
<?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">
<androidx.cardview.widget.CardView
android:id="#+id/cardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:paddingTop="5dp"
app:cardCornerRadius="7dp"
app:cardElevation="7dp"
app:cardUseCompatPadding="true"
app:contentPadding="5dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="#+id/thumbImage"
android:layout_width="110dp"
android:layout_height="110dp"
android:layout_gravity="start"
android:layout_margin="10dp"
tools:srcCompat="#drawable/ic_launcher_background" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="125dp"
android:orientation="vertical">
<TextView
android:id="#+id/restaurantName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="10dp"
android:textColor="#color/yellow"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:id="#+id/restaurantAddress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:textColor="#color/black"
android:textSize="14sp"
android:textStyle="normal" />
<TextView
android:id="#+id/restaurantHours"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:textColor="#color/black"
android:textSize="12sp"
android:textStyle="bold" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
While I was using json file it worked. But when I tried to retrieve data from realtime database firebase, it got stuck. I don't know, where does it go wrong. And also I can't retrieve the data from realtime database too.

Why my realtime databaase cannot be worked?

I have faced the problem that my firebase cannot be worked as well and it just shows me nothing ( white page ) in my application. I need to use firebase to show the material in the recycler view. However, as the new user for firebase, I set my recycler view in string form and after it, I also want to use as one is image one is text. But I think that I need to fix the first problem as well. Can somebody help me? Thank you for your help!!
My original code :
package com.example.assignment_mad
import android.content.ContentValues.TAG
import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import android.widget.Toast
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
import com.example.assignment_mad.databinding.ActivityMainBinding
import com.example.assignment_mad.databinding.FragmentNotificationBinding
import com.example.assignment_mad.databinding.FragmentSearchPageBinding
import com.google.android.material.imageview.ShapeableImageView
import com.google.android.material.tabs.TabLayout
import com.google.firebase.database.*
import com.google.firebase.database.ktx.database
import com.google.firebase.ktx.Firebase
import kotlinx.android.synthetic.*
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.fragment_notification_.*
class Notification_Fragment : Fragment( ) {
val database=Firebase.database
val myRef=database.getReference("message")
private var _binding:FragmentNotificationBinding?=null
private val binding get()=_binding!!
private lateinit var dbref: DatabaseReference
private lateinit var newRecyclerView: RecyclerView
private lateinit var newArrayList: ArrayList<Company>
private lateinit var tempArrayList: ArrayList<Company>
lateinit var imageId:Array<Int>
lateinit var heading:Array<String>
lateinit var news:Array<String>
private var layoutManager: RecyclerView.LayoutManager? = null
private var adapter: RecyclerView.Adapter<NotificationAdapter.MyViewHolder>? = null
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
var views =inflater.inflate(R.layout.fragment_notification_, container, false)
newRecyclerView=views.findViewById(R.id.recyclerView)
// Inflate the layout for this fragment
return views
}
override fun onViewCreated(itemView: View, savedInstanceState: Bundle?) {
super.onViewCreated(itemView, savedInstanceState)
newArrayList= arrayListOf<Company>()
tempArrayList= arrayListOf<Company>()
getUserdata()
}
private fun getUserdata() {
dbref=FirebaseDatabase.getInstance().getReference("Notification")
dbref.addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
if (snapshot.exists()){
for (companySnapshot in snapshot.children){
val company=companySnapshot.getValue(Company::class.java)
newArrayList.add(company!!)
}
newRecyclerView.adapter=NotificationAdapter(newArrayList)
}
}
override fun onCancelled(error: DatabaseError) {
Log.w(TAG, "Failed to read value.", error.toException())
}
})
newRecyclerView.layoutManager=LinearLayoutManager(activity)
newRecyclerView.setHasFixedSize(true)
newRecyclerView.adapter=adapter
}
}
The adapter code :
package com.example.assignment_mad
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.imageview.ShapeableImageView
import kotlinx.android.synthetic.main.dropdown_item.view.*
class NotificationAdapter(private val companysList:ArrayList<Company>):RecyclerView.Adapter<NotificationAdapter.MyViewHolder>() {
private var mListener:onItemClickListener?=null
interface onItemClickListener{
fun onItemClick(position: Int)
}
fun setOnItemClickListener(listener: onItemClickListener){
mListener=listener
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val itemView=LayoutInflater.from(parent.context).inflate(R.layout.list_item,parent,false)
return MyViewHolder(itemView,mListener)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val currentItem=companysList[position]
holder.titleImage.text=currentItem.titleImage
// holder.titleImage.setImageResource(currentItem.titleImage)
holder.tvHeading.text=currentItem.heading
}
override fun getItemCount(): Int {
return companysList.size
}
//to insert the post detail
class MyViewHolder(itemView: View,listener: onItemClickListener?):RecyclerView.ViewHolder(itemView){
val titleImage:TextView=itemView.findViewById(R.id.title_image)
// val titleImage:ShapeableImageView=itemView.findViewById(R.id.title_image)
val tvHeading: TextView =itemView.findViewById(R.id.tvHeading)
init {
itemView.setOnClickListener{
listener?.onItemClick(adapterPosition)
}
}
}
}
Data :
package com.example.assignment_mad
data class Company(var titleImage:String?=null,var heading:String?=null)
//data class Company(var titleImage:Int,var heading:String)
The xml file ( as you see, actually i need image and text together ) :
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_margin="8dp">
<!-- <com.google.android.material.imageview.ShapeableImageView-->
<!-- android:layout_width="80dp"-->
<!-- android:layout_height="80dp"-->
<!-- android:id="#+id/title_image"-->
<!-- android:scaleType="centerCrop"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toTopOf="parent"-->
<!-- app:shapeAppearanceOverlay="#style/RoundCorner"-->
<!-- android:src="#drawable/company_logo_1"/> -->
<TextView
android:id="#+id/title_image"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textColor="#color/black"
android:text="Self Brief"
android:textSize="16dp"
android:textStyle="bold"
android:layout_marginStart="16dp"
android:layout_marginEnd="32dp"
android:layout_marginTop="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:id="#+id/tvHeading"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textColor="#color/black"
android:text="Candidate Biden Called Saudi Arable a Pareft eaft."
android:textSize="16dp"
android:textStyle="bold"
android:layout_marginStart="16dp"
android:layout_marginEnd="32dp"
android:layout_marginTop="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/title_image"
app:layout_constraintTop_toTopOf="parent"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_margin="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/title_image"
android:background="#color/underline"/>
</androidx.constraintlayout.widget.ConstraintLayout>
These is the problem faced. Or some one else can directly teach me how to set image for realtime database?
My database pic :
Your RecyclerView is showing no item because you are never initializing the adapter variable, which you are setting to your RecyclerView's adapter. Initialize adapter variable inside onViewCreated()
override fun onViewCreated(itemView: View, savedInstanceState: Bundle?) {
super.onViewCreated(itemView, savedInstanceState)
newArrayList= arrayListOf<Company>()
tempArrayList= arrayListOf<Company>()
adapter = NotificationAdapter(newArrayList) //Initialize adapter
getUserdata()
}
Inside onDataChange(), after adding data to newArrayList, notify adapter by calling notifyDataSetChanged() on adapter. It would update the RecyclerView.
private fun getUserdata() {
dbref=FirebaseDatabase.getInstance().getReference("Notification")
dbref.addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
if (snapshot.exists()){
for (companySnapshot in snapshot.children){
val company=companySnapshot.getValue(Company::class.java)
newArrayList.add(company!!)
}
adapter.notifyDataSetChanged()
}
}
override fun onCancelled(error: DatabaseError) {
Log.w(TAG, "Failed to read value.", error.toException())
}
})
newRecyclerView.layoutManager=LinearLayoutManager(activity)
newRecyclerView.setHasFixedSize(true)
newRecyclerView.adapter = adapter
}

Android Studio-Kotlin: App Crashes when launched with error FATAL EXCEPTION: main

Got the below error when I launched the app in the device... Checked Manifest file, deleted build file and restarted the IDE. Nothing worked out .. Please help!
MainActivity.kt:
package com.bharat.scand_app
import android.app.Activity
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Bundle
import android.provider.MediaStore
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.Button
import android.widget.ImageView
import androidx.appcompat.app.AppCompatActivity
import com.external.scanlibrary.ScanActivity
import com.external.scanlibrary.ScanConstants
import java.io.IOException
class MainActivity : AppCompatActivity() {
private val REQUEST_CODE = 99
lateinit private var scanButton: Button
lateinit private var cameraButton: Button
lateinit private var mediaButton: Button
lateinit private var scannedImageView: ImageView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
init()
}
private fun init() {
scanButton = (findViewById<Button>(R.id.scanButton))!!
scanButton.setOnClickListener(ScanButtonClickListener())
cameraButton = (findViewById<Button>(R.id.cameraButton))!!
cameraButton.setOnClickListener(ScanButtonClickListener(ScanConstants.OPEN_CAMERA))
mediaButton = (findViewById<Button>(R.id.galleryButton))!!
mediaButton.setOnClickListener(ScanButtonClickListener(ScanConstants.OPEN_MEDIA))
scannedImageView = (findViewById<ImageView>(R.id.scannedImage))!!
}
fun startScan(preference: Int) {
val intent = Intent(this, ScanActivity::class.java)
intent.putExtra(ScanConstants.OPEN_INTENT_PREFERENCE, preference)
startActivityForResult(intent, REQUEST_CODE)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK) {
val uri: Uri? = data?.extras!!.getParcelable(ScanConstants.SCANNED_RESULT)
var bitmap: Bitmap? = null
try {
bitmap = MediaStore.Images.Media.getBitmap(contentResolver, uri)
if (uri != null) {
contentResolver.delete(uri, null, null)
}
scannedImageView.setImageBitmap(bitmap)
} catch (e: IOException) {
e.printStackTrace()
}
}
}
private fun convertByteArrayToBitmap(data: ByteArray): Bitmap? {
return BitmapFactory.decodeByteArray(data, 0, data.size)
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.menu_main, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
val id: Int = item.getItemId()
return if (id == R.id.action_settings) {
true
} else super.onOptionsItemSelected(item)
}
}
private class ScanButtonClickListener : View.OnClickListener {
private var preference = 0
val mActivity : MainActivity
get() {
TODO()
}
constructor(preference: Int) {
this.preference = preference
}
constructor() {}
override fun onClick(v: View?) {
mActivity.startScan(preference)
Log.d("appLog", "Hello World")
}
}
Activity_main.xml:
<?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:id="#+id/newLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="#+id/cameraButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="150dp"
android:layout_marginTop="630dp"
android:layout_marginEnd="100dp"
android:layout_marginBottom="50dp"
android:text="Camera"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/galleryButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="630dp"
android:layout_marginEnd="20dp"
android:layout_marginBottom="50dp"
android:text="Gallery"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/cameraButton"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Error captured in logcat:
--------- beginning of crash
2020-07-09 21:50:00.093 7512-7512/com.myapp.scand_app E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.myapp.scand_app, PID: 7512
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.myapp.scand_app/com.bharat.scand_app.MainActivity}: kotlin.KotlinNullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3388)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3527)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2123)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7710)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:516)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
Caused by: kotlin.KotlinNullPointerException
at com.bharat.scand_app.MainActivity.init(MainActivity.kt:37)
at com.bharat.scand_app.MainActivity.onCreate(MainActivity.kt:34)
at android.app.Activity.performCreate(Activity.java:7820)
at android.app.Activity.performCreate(Activity.java:7809)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1318)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3363)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3527) 
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83) 
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2123) 
at android.os.Handler.dispatchMessage(Handler.java:107) 
at android.os.Looper.loop(Looper.java:214) 
at android.app.ActivityThread.main(ActivityThread.java:7710) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:516) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950) 
scanButton = (findViewById<Button>(R.id.scanButton))!!
You find scanButton, but there is no button with id of scanButton in activity_main.xml. Your findViewById call return null, and "!!" is the null assertion operator and it is throwing NPE at that line.
Solution : Add another button with id of scanButton in your activity_mail.xml

create a custom spinner adapter in android using kotlin

I'm trying make a spinner with a custom adapter to display images with text like the following
but I got lots of unresolved references so I think I'm doing something terribly wrong
I have two fragments the spinner is inside the second fragment
custome_spinner.xml is the custom layout file
android studio 3.1.2
kotlin_version = '1.2.30'
gradle:3.1.2
customeSpinnerAdapter.kt
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
class customeSpinnerAdapter : BaseAdapter{
override fun getItem(p0: Int): Any {
return flag.length
}
override fun getItemId(p0: Int): Long {
return null
}
override fun getCount(): Int {
return 0
}
val country:String
val flag:String
fun customeSpinnerAdapter(context:Context,name:String,image:String){
this.country = name
this.flag = image
val inflater = LayoutInflater.from(context)
}
override fun getView(p0: Int, p1: View?, p2: ViewGroup?): View {
val view = inflater.inflate(R.layout.custome_spinner)
spinner_image.setImageResource(flag)
spinner_country.setText(country)
return view
}
}
custome_spinner.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="#+id/spinner_image"
android:layout_width="50dp"
android:layout_height="50dp"
android:padding="5dp"
android:src="#drawable/us" />
<TextView
android:id="#+id/spinner_country"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:layout_gravity="center"
android:text="Custom Text"
android:textColor="#000" />
</LinearLayout>
the widget inside fragment_second.xml
<Spinner
android:id="#+id/spinner"
android:layout_width="368dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="12dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/from_textView" />
Your problem lies in customeSpinnerAdapter.kt
customeSpinnerAdapter.kt
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
class customeSpinnerAdapter : BaseAdapter{
override fun getItem(p0: Int): Any {
return flag.length
}
override fun getItemId(p0: Int): Long {
return null
}
override fun getCount(): Int {
return 0
}
val country:String
val flag:String
//Add this
val inflater : LayoutInflater
fun customeSpinnerAdapter(context:Context,name:String,image:String){
this.country = name
this.flag = image
//val inflater = LayoutInflater.from(context)
inflater = LayoutInflater.from(context)
}
override fun getView(p0: Int, p1: View?, p2: ViewGroup?): View {
val view = inflater.inflate(R.layout.custome_spinner)
spinner_image.setImageResource(flag)
spinner_country.setText(country)
return view
}
}

Resources