This is the code:
class MainActivity : AppCompatActivity() {
lateinit var txtForgotPassword: TextView
lateinit var register: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
txtForgotPassword = findViewById(R.id.frgtpass)
txtForgotPassword.setOnClickListener {
val intent=Intent(this#MainActivity,Register::class.java)
startActivity(intent)
}
}
}
This is the error I faced:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.vishesh.foodrunner/com.vishesh.foodrunner.Register}: java.lang.NullPointerException
From what I can see from the logs you have a property in MainActivity line 17 which you assigned lateinit property but forgot to initialize it. I am not sure if you used it or not but give a base value to it and the error will go away you can always change as it is a var variable.
Related
I am trying to pass array list data to one of my fragments in the nav bar from main activity. Is there a simple way to implement this? Or should I use activity instead of the fragment? I need to pass the array list data to my HomeFragment and use recycler view adapter in the fragment, but now the issue is I don't know how to pass data because I am using bottom navigation view and Android Navigation component.
Main Activity
package com.example.a5t1v2
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.MenuItem
import android.widget.GridView
import androidx.navigation.NavArgument
import androidx.navigation.NavController
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.bottomnavigation.BottomNavigationView
class MainActivity : AppCompatActivity() {
private lateinit var bottomNavigationView: BottomNavigationView
private lateinit var navController: NavController
private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var shoppingItemList:MutableList<Item>
private lateinit var recyclerView: RecyclerView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initUI()
val dbHelper = DBHelper(this)
populateDB(dbHelper)
shoppingItemList = dbHelper.getAlItems()
}
private fun populateDB(dbHelper: DBHelper) {
dbHelper.insertItem(Item("Bread",1,"Default", urgent = true, bought = false,null))
dbHelper.insertItem(Item("Chocolate Bar",1,"Small", urgent = false, bought = false,null))
dbHelper.insertItem(Item("Instant noodle",1,"Default", urgent = false, bought = false,null))
dbHelper.insertItem(Item("Juice",2,"Large", urgent = false, bought = false,null))
dbHelper.insertItem(Item("Milk",3,"Large", urgent = true, bought = false,null))
dbHelper.insertItem(Item("Shampoo",1,"Small", urgent = false, bought = true,"24 Aug 2020"))
dbHelper.insertItem(Item("Shower Gel",1,"Large", urgent = false, bought = true,"24 Aug 2020"))
}
private fun initUI() {
appBarConfiguration = AppBarConfiguration(setOf(R.id.urgentListFragment, R.id.homeFragment, R.id.completedListFragment))
bottomNavigationView = findViewById<BottomNavigationView>(R.id.bottomNavigationView)
navController = findNavController(R.id.fragmentContainerView)
setupActionBarWithNavController(navController,appBarConfiguration)
bottomNavigationView.setupWithNavController(navController)
}
}
An easy and good way would be to use a sharedViewModel.
Create a ViewModel and declare a LiveData in it.
class MainViewModel: ViewModel () {
private val arrayListLiveData = MutableLiveData<ArrayList<Item>>()
}
Inside Activity, create an instance of this ViewModel in the acitivity, and you can send your arrayList from here using post on the liveData
class MainActivity : AppCompatActivity() {
private lateinit var mainViewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mainViewModel = ViewModelProvider(this).get(MainViewModel::class.java)
mainViewModel.arrayListLiveData.post(YOUR_ARRAY_LIST_DATA)
}
}
You can observe the same liveData inside the fragment, and would receive the posted arrayList there, from the Activity
class TestFragment : Fragment(R.layout.test) {
private lateinit var mainViewModel: MainViewModel
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mainViewModel = ViewModelProvider(requireActivity()).get(MainViewModel::class.java)
mainViewModel.arrayListLiveData.observe(viewLifecycleOwner) { arrayList ->
//Perform desired operation with the array list
}
}
}
how to solve this kind of problem starActivityForResult please any budy guide me to solve this
startActivityForResult is deprecated following is new the way. Here is a full source code example
MainActivity
class MainActivity : AppCompatActivity() {
private lateinit var tvResult:TextView
private lateinit var btnNext:Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
tvResult = findViewById(R.id.tv_result)
btnNext = findViewById(R.id.btn_next)
btnNext.setOnClickListener {
openActivityForResult(Intent(this,SampleActivity::class.java))
}
}
private var resultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
val mIntent: Intent? = result.data
val mDataString = mIntent?.getStringExtra("result_data")
tvResult.text = mDataString
}
}
private fun openActivityForResult(mIntent: Intent) {
resultLauncher.launch(mIntent)
}
}
SampleActivity
class SampleActivity : AppCompatActivity() {
private lateinit var btnDone: Button
private val sampleData = "Sample Activity Result Data"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_sample)
btnDone = findViewById(R.id.btn_done)
btnDone.setOnClickListener{
returnForResult()
}
}
private fun returnForResult(){
val replyIntent = Intent()
replyIntent.putExtra(
"result_data",
sampleData
)
setResult(Activity.RESULT_OK, replyIntent)
finish()
}
}
startActivityForResult is deprecated, meaning that it will no longer be supported going forward. That is why Android Studio is showing you the lines through the code. Instead, review this Stackoverflow post on alternative options:
OnActivityResult method is deprecated, what is the alternative?
I am using Dagger Hilt for dependecy Injection
I have a class -
SessionManager
class SessionManager (context: Context){
private val dataStore: DataStore<Preferences> = context.createDataStore(
name = "session"
)
companion object{
val IS_LOGIN = preferencesKey<Boolean>(name = "is_login")
}
suspend fun setLogin(isLogin: Boolean){
dataStore.edit {
preferences ->
preferences[IS_LOGIN] = isLogin
}
}
}
I am trying to call the setLogin func in an activity like this -
MainActivity
#AndroidEntryPoint
class MainActivity #Inject constructor(private val sessionManager: SessionManager) :
AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
lifecycleScope.launch {
sessionManager.setLogin(true)
}
}
MyApplication
#HiltAndroidApp
class MyApplication : Application() {
}
Manifest
<application
android:name=".MyApplication"
android:allowBackup="true"/>
As you can see, I have used the #AndroidEntryPoint Annotation but I still get this runtime error
*java.lang.Class<com.app.app.activities.MainActivity> has no zero argument constructor*
For MainActivity I think you cannot do contructor injection, so try field injection as:
#AndroidEntryPoint
class MainActivity : AppCompatActivity() {
#Inject
lateinit var sessionManager: SessionManager
override fun onCreate(savedInstanceState: Bundle?) {
lifecycleScope.launch {
sessionManager.setLogin(true)
}
}
}
Now you should be able to use sessionManager inside onCreate
I am trying to pass over a text to my second activity but it does not seem to be working correctly.
For my main activity i have a a textview and the text says 'Cat'. When the image on the first activity is pressed on, I want "Cat" to be passed over to the second activity. The second activity's textview should also display "Cat", however when I do this, it will show up as "Info(name=Cat)" rather then just "Cat".
I am not sure where i went wrong.
This is my main activity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val image = findViewById<ImageView>(R.id.imageView)
val text = findViewById<TextView>(R.id.textView)
image.setOnClickListener {
val intent= Intent(this, MainActivity2::class.java).apply {
putExtra("name", Info("Cat"))
}
startActivity(intent)
}
}
}
My parcelable class
#Parcelize
data class Info(val name : String) : Parcelable {
}
This is my second activity
class MainActivity2 : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main2)
val info = intent.getParcelableExtra<Info>("name")
val name = findViewById<TextView>(R.id.textView2)
name.text = info.toString()
}
}
You're converting the whole Info data class to its string representation. You only want the name property from the data class.
name.text = info.name
I have a problem calling a second activity using a password recovery button. I get the app stopped.
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
fun goToRecover(view: View) {
val intent = Intent(this,RecoverPasswordActivity::class.java)
this.startActivity(intent)
}
}
Did you try adding the onClick in the XML-layout like this?
android:onClick="/*your method name*/"
If so, make sure that there are no typos. In your case it would probably be:
android:onClick="addOne"
OR
You can also listen for the click events programmatically. like below:
set the Button in OnCreate method:
var goToRecoverBtn = findViewById(R.id./*id name here*/)
after that add the ClickListener to the goToRecoverBtn:
goToRecoverBtn.setOnClickListener{
// do anything whatever you want
}
OR
MainActivity code looks like below
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var goToRecoverBtn = findViewById(R.id./*id name here*/)
goToRecoverBtn.setOnClickListener{
val intent = Intent(this#MainActivity, RecoverPasswordActivity::class.java)
startActivity(intent)
}
}
}
BTW could you please show us your .xml file?