lateinit property mAdapter has not been initialized. How to solve this problem? - android-studio

MainActivity.kt
class MainActivity : AppCompatActivity(), NewsItemclicked {
private lateinit var mAdapter: NewsListAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
recyclerView.layoutManager = LinearLayoutManager(this)
fetchData()
val adapter = NewsListAdapter( this)
recyclerView.adapter = mAdapter
}
private fun fetchData(){
val url = "https://saurav.tech/NewsAPI/top-headlines/category/sports/in.json"
val jsonObjectRequest = JsonObjectRequest(
Request.Method.GET,
url,
null,
Response.Listener {
val newsJsonArray = it.getJSONArray("articles")
val newsArray = ArrayList<News>()
for(i in 0 until newsJsonArray.length()){
val newsJsonObject = newsJsonArray.getJSONObject(i)
val news = News(
newsJsonObject.getString("title"),
newsJsonObject.getString("author"),
newsJsonObject.getString("url"),
newsJsonObject.getString("urlToImage")
)
newsArray.add(news)
}
mAdapter.updateNews(newsArray)
},
Response.ErrorListener{
}
)
MySingleton.getInstance(this).addToRequestQueue(jsonObjectRequest)
}
override fun onItemClicked(item: News) {
}
}
On the above MainActivity.kt of a News app is given.When I try to run the app the app is crashing. It is showing that lateinit property mAdapter has not been initialized. Please help me to figure out the problem.Please try to explain the simplest way as I am a beginner to Android so it is quite difficult to me to understand it quickly.
Error
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.newstoday, PID: 10633
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.newstoday/com.example.newstoday.MainActivity}: kotlin.UninitializedPropertyAccessException: lateinit property mAdapter has not been initialized
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2646)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
Caused by: kotlin.UninitializedPropertyAccessException: lateinit property mAdapter has not been initialized

It seems like you're instantiating your adapter and store the reference in a local variable (adapter) instead of the global one (mAdapter) which you specifically created to update its data once you receive the response from the network request.
If you change your code to:
mAdapter = NewsListAdapter(this)
the crash would be solved.

Related

can't use a toast message in the recyclerview

I am making recyclerview in kotlin in android studio. I'm trying to set up an event listener that puts a button in the recyclerview and outputs a toast message. Even if this#[activity name] is entered instead of this in context, a toast message is not displayed. What went wrong?
The error code is as follows.
Unresolved reference: #UpdateActivity
class UpdateActivity : AppCompatActivity() {
private val vBinding by lazy {ActivityUpdateBinding.inflate(layoutInflater)}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(vBinding.root)
var recyclerViewAdapter = CustomAdapter()
recyclerViewAdapter.listData = arrayListOf<String>("a", "b", "c")
vBinding.uploadedRecyclerView.adapter = recyclerViewAdapter
vBinding.uploadedRecyclerView.layoutManager = LinearLayoutManager(this)
} // onCreate End
class CustomAdapter:RecyclerView.Adapter<CustomAdapter.Holder>(){
var listData = arrayListOf<String>()
class Holder(val vBinding:UploadedRecyclerBinding):RecyclerView.ViewHolder(vBinding.root){
fun setData(name:String){
vBinding.name.text = name
vBinding.getBtn.setOnClickListener {
**Toast.makeText(this#UpdateActivity, "test", Toast.LENGTH_SHORT).show()**
// ↑A compilation error occurs here.**
}
}
} // Holder end
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
val vBinding = UploadedRecyclerBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return Holder(vBinding)
}
override fun onBindViewHolder(holder: Holder, position: Int) {
val name = listData[position]
holder.setData(name)
}
override fun getItemCount(): Int {
return listData.size
}
} // CustomAdapter end
} // UpdateActivity end
you could try put context into constructor of adapter when you create it, and use this context to show a toast. something like this:
class CustomAdapter(
private val mContext: Context
):RecyclerView.Adapter<CustomAdapter.Holder>(){
and in holder class:
Toast.makeText(mContext, "test", Toast.LENGTH_SHORT).show()
finally, when you create adapter in activity:
var recyclerViewAdapter = CustomAdapter(this)
Normally, we'll create adapter class in another file, so use this#UpdateActivity in adapter is bad idea
Instead of using the local context in Toast, always use applicationContext when showing it. So, you should replace that creation of Toast message as,
Toast.makeText(applicationContext, "test", Toast.LENGTH_SHORT).show()

E/RecyclerView: No adapter attached; skipping layout / Kotlin

I have been reading the different answers here on stackoverflow and on this blog post and tried to implement their solutions but I am still getting the error. The code is from a yt tutorial. I hope someone can help me. Thanks
Error E/RecyclerView: No adapter attached; skipping layout
My Adapter
This is my Main Activity
class MainActivity : AppCompatActivity(), IDrinkLoadListener {
lateinit var drinkLoadListener: IDrinkLoadListener
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
init()
loadDrinkFromFirebase()
}
private fun loadDrinkFromFirebase() {
val drinkModels : MutableList<DrinkModel> = ArrayList()
FirebaseDatabase.getInstance()
.getReference("Drink")
.addListenerForSingleValueEvent(object: ValueEventListener{
override fun onDataChange(snapshot: DataSnapshot) {
if(snapshot.exists()) {
for (drinkSnapshot in snapshot.children) {
val drinkModel = drinkSnapshot.getValue(DrinkModel::class.java)
drinkModel!!.key = drinkSnapshot.key
drinkModels.add(drinkModel)
}
drinkLoadListener.onDrinkLoadSuccess(drinkModels)
} else
drinkLoadListener.onDrinkLoadFailed("Drink items not exist")
}
override fun onCancelled(error: DatabaseError) {
drinkLoadListener.onDrinkLoadFailed(error.message)
}
})
}
private fun init() {
drinkLoadListener = this
val gridLayoutManager = GridLayoutManager(this, 2)
recycler_drink.layoutManager = gridLayoutManager
recycler_drink.addItemDecoration(SpaceItemDecoration())
}
override fun onDrinkLoadSuccess(drinkModelList: List<DrinkModel>?) {
val adapter = MyDrinkAdapter(this,drinkModelList!!)
recycler_drink.adapter = adapter
}
override fun onDrinkLoadFailed(message: String?) {
Snackbar.make(mainLayout,message!!,Snackbar.LENGTH_LONG).show()
}
}
class SpaceItemDecoration : RecyclerView.ItemDecoration() {
override fun getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
) {
if(parent.getChildLayoutPosition(view) % 2 != 0)
{
outRect.top= 25
outRect.bottom= -25
}else outRect.top = 0
}
}
Thanks in advance!!!
That happens because the adapter is attached to the recycler after an asynchronous operation on onDrinkLoadSuccess
You can attach the adapter to the recycler during onCreate and then the onDrinkLoadSuccess update it with the data.
The ListAdapter class has a submit method for it. If you are using plain recycler is usually something like this:
Recycler ... {
private val dataList = mutableListOf()
fun update(list: List<YourType>) {
dataList.clear()
dataList.addAll(list)
notifyDataDetChanged() //important updates the UI
}
}
There are more specific updates methods like notifyItemRangeChanged, etc.
Also there are helpers for finding difference in the data sets DiffUtil.ItemCallback

kotlin app crashes when going one to another activity

i have 3 activitiy when i start my app i can go 1 activity to second but i cant go third it crashes
this is code of my third( last activity )
class thirdActivity3 : AppCompatActivity() {
private lateinit var textView: TextView
private lateinit var textView2: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_third3)
textView = findViewById(R.id.textView)
textView2 = findViewById(R.id.textView2)
val extras = intent.extras
if(extras != null){
textView.text = extras.getString("NAME") //getString("NAME","")
textView2.text = extras.getInt("AGE").toString() //getInt("AGE",0).toString()
}
}
}
and this is my second activity
class secondActivity2 : AppCompatActivity() {
private lateinit var inputTextAge:EditText
private lateinit var finishButton: Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_second2)
inputTextAge=findViewById(R.id.inputTextAge)
finishButton=findViewById(R.id.finishButton)
val extras = intent.extras
var name = ""
if (extras != null){
name=extras.getString("PERSON_NAME","")
}
finishButton.setOnClickListener {
val age = finishButton.text.toString().toInt()
val intent = Intent(this,thirdActivity3::class.java)
intent.putExtra("NAME",name)
intent.putExtra("AGE",age)
startActivity(intent)
}
}
}
i am trying to make wizard for learning but my code have some problems. i have 3 activitys in kotling but when i go second activity to third it's stopping but its workd when i going first to second
2020-11-27 18:50:41.472 19343-19343/com.example.myapplication E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.myapplication, PID: 19343
java.lang.NumberFormatException: For input string: "Finish"
at java.lang.Integer.parseInt(Integer.java:615)
at java.lang.Integer.parseInt(Integer.java:650)
at com.example.myapplication.secondActivity2$onCreate$1.onClick(secondActivity2.kt:33)
at android.view.View.performClick(View.java:7125)
at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:992)
at android.view.View.performClickInternal(View.java:7102)
at android.view.View.access$3500(View.java:801)
at android.view.View$PerformClick.run(View.java:27336)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
this is from logcat
Looking at the error message, it looks like your problem is this line:
val age = finishButton.text.toString().toInt()
The error is saying that you're trying to parse the string "Finish" as a number. It makes sense from this line that you're doing that. You have a button named "Finish". You get the text from the button and then call toInt() on that text, and you get this error.
What do you expect this line to do? Why do you expect querying a button's text to return an integer that represents age?

E/ModuleIdSetter: exception when setting module id. What does this error mean?

I was building an app on android studio and encountered this error E/ModuleIdSetter: exception when setting module id. I have no idea what this error is about and I would like to know what it is and how to resolve it. The full error is below.
2020-07-21 16:07:06.626 28147-28311/? E/ModuleIdSetter: exception when setting module id
java.lang.IllegalStateException: Unable to get current module info in ModuleManager created with non-module Context
at com.google.android.chimera.config.ModuleManager.getCurrentModule(:com.google.android.gms#202414040#20.24.14 (120700-319035315):2)
at aeua.a(:com.google.android.gms#202414040#20.24.14 (120700-319035315):4)
at aeud.b(:com.google.android.gms#202414040#20.24.14 (120700-319035315):9)
at aeql.a(Unknown Source:0)
at rnb.a(:com.google.android.gms#202414040#20.24.14 (120700-319035315):0)
at rjk.c(:com.google.android.gms#202414040#20.24.14 (120700-319035315):1)
at rji.b(:com.google.android.gms#202414040#20.24.14 (120700-319035315):1)
at rlz.b(:com.google.android.gms#202414040#20.24.14 (120700-319035315):6)
at rlz.c(:com.google.android.gms#202414040#20.24.14 (120700-319035315):6)
at rlz.b(:com.google.android.gms#202414040#20.24.14 (120700-319035315):10)
at rlz.a(:com.google.android.gms#202414040#20.24.14 (120700-319035315):17)
at rlz.g(:com.google.android.gms#202414040#20.24.14 (120700-319035315):3)
at sbg.a(:com.google.android.gms#202414040#20.24.14 (120700-319035315):2)
at sag.a(:com.google.android.gms#202414040#20.24.14 (120700-319035315):10)
at rzx.a(:com.google.android.gms#202414040#20.24.14 (120700-319035315):0)
at saa.handleMessage(:com.google.android.gms#202414040#20.24.14 (120700-319035315):28)
at android.os.Handler.dispatchMessage(Handler.java:107)
at aeiw.a(:com.google.android.gms#202414040#20.24.14 (120700-319035315):2)
at aeiw.dispatchMessage(:com.google.android.gms#202414040#20.24.14 (120700-319035315):14)
at android.os.Looper.loop(Looper.java:214)
at android.os.HandlerThread.run(HandlerThread.java:67)
System services not available to Activities before onCreate().
For example
This will throw an exception
private var audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
override fun onCreate(savedInstanceState: Bundle?) {
}
But, this won't
private lateinit var audioManager: AudioManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
}

How to fix "lateinit property YYY has not been initialized"

I have a class that makes bluetooth connection and gets a PID from an OBD bluetooth dongle that its connected in the car.
But when calling the method for getting RPM then I have an Exception about not initialazing that property.
class BluetoothOBDManager : OBDManager {
lateinit var context: Context
private lateinit var input: InputStream
private lateinit var output: OutputStream
private lateinit var rpmCommand: RPMCommand
private lateinit var coolantTempCommand: EngineCoolantTemperatureCommand
private lateinit var airIntakeTempCommand: AirIntakeTemperatureCommand
private lateinit var mmSocket : BluetoothSocket
fun connect(deviceString: String) {
var adapter: BluetoothAdapter = getDefaultAdapter()
val device = adapter.getRemoteDevice(deviceString)
val uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")
val mmSocket:BluetoothSocket=device.createRf....Record(uuid)
mmSocket.let { socket ->
socket.connect()
}
input = mmSocket.inputStream
output = mmSocket.outputStream
if (mmSocket.isConnected) {
println("output.write =1")
output.write(1)
}
rpmCommand = RPMCommand() //This is the INIT of the propert
}
override fun getCurrentRpm(): Int {
rpmCommand.run(input, output) // This line throughs the EXCEPTION
return rpmCommand.rpm
}
}
This is how I call the method from another class
BluetoothOBDManager().connect(deviceString)
var rpm = BluetoothOBDManager().getCurrentRpm()
rpmTextView.setText(rpm)
The exception
E/AndroidRuntime: FATAL EXCEPTION: main
Process: gr.obd.logger, PID: 17486
kotlin.UninitializedPropertyAccessException: lateinit property rpmCommand has not been initialized
I have tried to INIT the property inside the method but no luck
override fun getCurrentRpm(): Int {
rpmCommand = RPMCommand()
rpmCommand.run(input, output) // This line throughs the EXCEPTION
return rpmCommand.rpm
}
BluetoothOBDManager().connect(deviceString)
var rpm = BluetoothOBDManager().getCurrentRpm()
Your code creates a BluetoothOBDManager, connects it (initializing rpmCommand), then throws it away, creates a new BluetoothOBDManager with everything uninitialized and tries to call getCurrentRpm on it. It likely should be
val obdManager = BluetoothOBDManager()
obdManager.connect(deviceString)
val rpm = obdManager.getCurrentRpm()
This doesn't explain why you would get
I have tried to INIT the property inside the method but no luck
but that really shouldn't happen; I expect something else is going wrong.

Resources