Search code examples
androidkotlinandroid-room

Android Studio Dolphin (Kotlin) : App crashes when launching


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


Solution

  • 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.