I tried creating a simple database in which i can add a product. delete products, and search. I followed a tutorial on a book as i am a beginner in kotlin and android studio.
Here is the Manifest :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.RoomDemo"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
</application>
</manifest>
Here is my main activity :
package com.ebookfrenzy.roomdemo
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.fragment.app.FragmentActivity
import com.ebookfrenzy.roomdemo.ui.main.MainFragment
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (savedInstanceState == null) {
supportFragmentManager.beginTransaction()
.replace(R.id.container, MainFragment.newInstance())
.commitNow()
}
}
}
here is the fragmentmain.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".ui.main.MainFragment">
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp">
<TextView
android:id="@+id/productID"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/product_id"
android:textSize="18sp" />
<TextView
android:id="@+id/text_not_assigned"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/not_assigned"
android:textSize="18sp" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp">
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/product_name"
android:textSize="18sp" />
<EditText
android:id="@+id/productName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="none"
android:text=""
android:textSize="18sp"
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp">
<TextView
android:id="@+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/product_quantity"
android:textSize="18sp" />
<EditText
android:id="@+id/productQuantity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="number"
android:textSize="18sp"
tools:ignore="TouchTargetSizeCheck,SpeakableTextPresentCheck" />
</TableRow>
</TableLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:gravity="center_horizontal"
android:orientation="horizontal">
<Button
android:id="@+id/addButton"
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/add"
android:textColor="@color/black" />
<Button
android:id="@+id/findButton"
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Find"
android:textColor="@color/black" />
<Button
android:id="@+id/deleteButton"
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/delete"
android:textColor="@color/black" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:baselineAligned="false" />
</LinearLayout>
</LinearLayout>
Finally, here is the logcat (only errors) :
2023-01-18 20:14:36.108 1950-1950/com.ebookfrenzy.roomdemo E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.ebookfrenzy.roomdemo, PID: 1950
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.ebookfrenzy.roomdemo/com.ebookfrenzy.roomdemo.MainActivity}: java.lang.NullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3676)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3813)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:101)
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:2308)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7898)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
Caused by: java.lang.NullPointerException
at com.ebookfrenzy.roomdemo.ui.main.MainFragment.getBinding(MainFragment.kt:32)
at com.ebookfrenzy.roomdemo.ui.main.MainFragment.listenerSetup(MainFragment.kt:65)
at com.ebookfrenzy.roomdemo.ui.main.MainFragment.onCreate(MainFragment.kt:44)
at androidx.fragment.app.Fragment.performCreate(Fragment.java:2981)
at androidx.fragment.app.FragmentStateManager.create(FragmentStateManager.java:474)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:257)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1840)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1758)
at androidx.fragment.app.FragmentManager.execSingleAction(FragmentManager.java:1670)
at androidx.fragment.app.BackStackRecord.commitNow(BackStackRecord.java:317)
at com.ebookfrenzy.roomdemo.MainActivity.onCreate(MainActivity.kt:16)
at android.app.Activity.performCreate(Activity.java:8290)
at android.app.Activity.performCreate(Activity.java:8269)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1384)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3657)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3813)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:101)
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:2308)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7898)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
as requested, here is the mainFragment file:
import androidx.lifecycle.ViewModelProvider
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import com.ebookfrenzy.roomdemo.ProductRepository
import com.ebookfrenzy.roomdemo.MainActivity
import com.ebookfrenzy.roomdemo.ProductDao
import com.ebookfrenzy.roomdemo.ui.main.ProductListAdapter
import android.view.ViewGroup
import com.ebookfrenzy.roomdemo.R
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager
import com.ebookfrenzy.roomdemo.Product
import androidx.fragment.app.viewModels
import java.util.*
import com.ebookfrenzy.roomdemo.databinding.FragmentMainBinding
//preparation du main fragment
class MainFragment : Fragment() {
private var adapter: ProductListAdapter? = null
companion object {
fun newInstance() = MainFragment()
}
val viewModel: MainViewModel by viewModels()
private var _binding: FragmentMainBinding? = null
private val binding get() = _binding!!
// si ya une erreur c'est ici
private fun recyclerSetup(){
adapter = ProductListAdapter(R.layout.product_list_item)
binding.recyclerView.layoutManager = LinearLayoutManager(context)
binding.recyclerView.adapter = adapter
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
listenerSetup()
observerSetup()
recyclerSetup()
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentMainBinding.inflate(inflater, container, false)
return binding.root
}
private fun clearFields() {
binding.productID.text = ""
binding.productName.setText("")
binding.productQuantity.setText("")
}
//ajout de bouton listeners
private fun listenerSetup() {
binding.addButton.setOnClickListener {
val name = binding.productName.text.toString()
val quantity = binding.productQuantity.text.toString()
if (name != "" && quantity != "") {
val product = Product(name, Integer.parseInt(quantity))
viewModel.insertProduct(product)
clearFields()
} else {
binding.productID.text = " Infos Incompletes "
}
}
binding.findButton.setOnClickListener {
viewModel.findProduct(binding.productName.text.toString())
}
binding.deleteButton.setOnClickListener {
viewModel.deleteProduct(
binding.productName.text.toString()
)
clearFields()
}
}
private fun observerSetup() {
viewModel.getAllProducts()
?.observe(this, Observer { products -> products?.let { adapter?.setProductList(it) } })
viewModel.getSearchResults().observe(this, Observer { products ->
products?.let {
if(it.isNotEmpty()){
binding.productID.text = String .format(Locale.US, "%d", it[0].id)
binding.productName.setText(it[0].productName)
binding.productQuantity.setText(String.format(Locale.US,"%d",it[0].quantity))
}
else {
binding.productID.text = "No Match"
}
}
})
}
}
Thanks a lot for taking the time to help me !
i just tried to run the app on the android studio emulator and it displayed an error message saying : "RoomDemo keeps stoping" right after i launched the app. RoomDemo is the name of my app
The problem can be seen in the logcat extract.
Caused by: java.lang.NullPointerException
at com.ebookfrenzy.roomdemo.ui.main.MainFragment.getBinding(MainFragment.kt:32)
This makes it look like getBinding
returns null at line 32 in MainFragment. You didn't post the code for MainFragment
. Add this to the question for further assistance.
EDIT : Adding further information below now that MainFragment has been added to the question.
In onCreate
you are doing things that will try to use the binding
. But the binding
hasn't been assigned yet, this happens inside onCreateView
.
There is a lifecycle method for onViewCreated
which will be called after onCreateView
has returned. You can guarantee at this point binding will have been assigned and so invoking the various functions that are called inside onCreate
in onViewCreated
will prevent the null pointer exception.
You should read up on android lifecycle for an Activity, and Fragments. This will help you understand why you had the problem.