I am a beginner at programming. I have an error message when I start my app and do not know what to do with the code. Can someone help me please.
Here is my code:
Activity :
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val items = ArrayList<String>()
items.add("Test1")
items.add("Test2")
items.add("Test3")
listview1.adapter = Adapter1(this, items)
val transaction1 = supportFragmentManager.beginTransaction()
fragment1Button1.setOnClickListener{
transaction1.replace(R.id.fragment1Platz,Fragment1())
transaction1.commit()
}
}
}
Fragment :
class Fragment1 : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_fragment1, container, false)
}
}
Adapter:
class Adapter1 (context : Context, items : ArrayList<String>) : BaseAdapter() {
private val context: Context = context
private val items: ArrayList<String> = items
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
val listeneintrag = LayoutInflater.from(context).inflate(R.layout.adapter1_layout,parent, false)
listeneintrag.findViewById<TextView>(R.id.adapter_textfeld1).text = items.get(position)
return listeneintrag
}
override fun getItem(position: Int): String {
return items.get(position)
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getCount(): Int {
return items.size
}
}
Error stacktrace:
2020-02-01 13:37:17.972 10729-10729/? E/AndroidRuntime: FATAL
EXCEPTION: main Process: strauss2002.yannick.fragmentetest, PID: 10729
java.lang.RuntimeException: Unable to start activity
ComponentInfo{strauss2002.yannick.fragmentetest/strauss2002.yannick.fragmentetest.MainActivity}:
java.lang.IllegalStateException: listview1 must not be null at
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2778)
at
android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856)
at android.app.ActivityThread.-wrap11(Unknown Source:0) at
android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)
at android.os.Handler.dispatchMessage(Handler.java:106) at
android.os.Looper.loop(Looper.java:164) at
android.app.ActivityThread.main(ActivityThread.java:6494) at
java.lang.reflect.Method.invoke(Native Method) at
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807) Caused
by: java.lang.IllegalStateException: listview1 must not be null at
strauss2002.yannick.fragmentetest.MainActivity.onCreate(MainActivity.kt:29)
at android.app.Activity.performCreate(Activity.java:7009) at
android.app.Activity.performCreate(Activity.java:7000) at
android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1214)
at
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2731)
at
android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856)
at android.app.ActivityThread.-wrap11(Unknown Source:0) at
android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)
at android.os.Handler.dispatchMessage(Handler.java:106) at
android.os.Looper.loop(Looper.java:164) at
android.app.ActivityThread.main(ActivityThread.java:6494) at
java.lang.reflect.Method.invoke(Native Method) at
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Here is my updated Main Activity:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val listview1=findViewById<ListView>(R.id.listview1)
val items = ArrayList<String>()
items.add("Test1")
items.add("Test2")
items.add("Test3")
listview1.adapter = Adapter1(this, items)
val transaction1 = supportFragmentManager.beginTransaction()
fragment1Button1.setOnClickListener{
transaction1.replace(R.id.fragment1Platz,Fragment1())
transaction1.commit()
}
}
}
And here is the new error message:
2020-02-02 11:15:15.935 12764-12764/strauss2002.yannick.fragmentetest E/AndroidRuntime: FATAL EXCEPTION: main
Process: straus
s2002.yannick.fragmentetest, PID: 12764
java.lang.RuntimeException: Unable to start activity ComponentInfo{strauss2002.yannick.fragmentetest/strauss2002.yannick.fragmentetest.MainActivity}: java.lang.IllegalStateException: listview1 must not be null
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2778)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Caused by: java.lang.IllegalStateException: listview1 must not be null
at strauss2002.yannick.fragmentetest.MainActivity.onCreate(MainActivity.kt:28)
at android.app.Activity.performCreate(Activity.java:7009)
at android.app.Activity.performCreate(Activity.java:7000)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1214)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2731)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Here is the xml of the activity_main:
<?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=".MainActivity">
<FrameLayout
android:id="#+id/fragment1Platz"
android:layout_width="410dp"
android:layout_height="495dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent">
</FrameLayout>
<Button
android:id="#+id/fragment1Button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="60dp"
android:text="Öffne Fragment 1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.529"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Here is the xml of the fragment_fragment1:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Fragment1">
<!-- TODO: Update blank fragment layout -->
<ListView
android:id="#+id/listview1"
android:layout_width="match_parent"
android:layout_height="322dp"/>
</FrameLayout>
Here is the xml of the adapter1_layout:
<?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/frameLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/adapter_textfeld1"
android:layout_width="137dp"
android:layout_height="53dp"
android:layout_marginTop="128dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Because you didn't call findViewById for listview1.
Add listview1=findViewById(R.id.yourListViewIdInXml); just after setContentView method of oncreate
Or if you are using kotlin synthetic then make sure that listview1 resides in activity_main.xml file
Update
The problem persists because you are calling findViewById on an id(listview1) which is not available in activity_main.xml. Note that in case of activities, when you call findViewById it searches id in the layout file which is passed in setContentView method, that is activity_main.xml in your case. So when you called findViewById<ListView>(R.id.listview1) it searches listview1 in activity_main.xml, but as we know that there is no view available in activity_main.xml which has id=listview1, so findViewById simply returns null and that's why you are getting this error. So to get rid of this exception change:
val listview1=findViewById<ListView>(R.id.listview1)
to this:
val listview1=findViewById<ListView>(R.id.kontaktliste)
I had the same issue. I resolved just putting the setContentView(activity_layout) in the onResume method.
I don't know why this error hasn't occurred in other activities with a listView
The reason you are getting Null Exception is that you are trying to access listView1 before the fragment view is completely created which means listView1 doesn't exist yet.
So you have to move that part of the code you have in your MainActivity to the onCreateView method of your fragment like so:
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val rootView = inflater.inflate(R.layout.fragment_fragment1, container, false)
val items = ArrayList<String>()
items.add("Test1")
items.add("Test2")
items.add("Test3")
//THIS IS HOW YOU REFERENCE YOU VIEWS IN A FRAGMENT IN KOTLIN
rootView.listview1.adapter = Adapter1(this, items)
return rootView
}
And pay attention that in a fragment, you have to reference the views through the inflated rootView for your fragment.
Related
I'm trying to set up a Wear OS project. I have some experience with normal android development but Wear os is new for me.
I'm used to just having one MainActivity and some fragments. But I'm trying to make that work for Wear OS but with no success. It keeps crashing when I want to use viewBinding in the OverviewFragment.kt.
I got the following project now:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.wear.widget.BoxInsetLayout 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:padding="#dimen/box_inset_layout_padding"
tools:context=".MainActivity"
tools:deviceIds="wear">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="#dimen/inner_frame_layout_padding"
app:layout_boxedEdges="left|right">
<include
layout="#layout/content_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
</androidx.wear.widget.BoxInsetLayout>
content_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.wear.widget.BoxInsetLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<fragment
android:id="#+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="#navigation/nav_graph" />
</androidx.wear.widget.BoxInsetLayout>
fragment_overview.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.OverviewFragment">
<TextView
android:id="#+id/tvOverview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:text="overview"
android:textAlignment="center" />
</FrameLayout>
MainActivity.kt
class MainActivity : FragmentActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
}
}
OverviewFragment.kt
class OverviewFragment : Fragment() {
private var _binding: FragmentOverviewBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_overview, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.tvOverview.setOnClickListener {
println("great")
}
}
}
Just a simple design, but it does not like the binding.tvOverview.setOnClickListener part in OverviewFragment.kt. It just keeps crashing.
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.krakert.tracker, PID: 7261
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.krakert.tracker/com.krakert.tracker.MainActivity}: android.view.InflateException: Binary XML file line #17: Binary XML file line #8: Error inflating class fragment
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2817)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Caused by: android.view.InflateException: Binary XML file line #17: Binary XML file line #8: Error inflating class fragment
Caused by: android.view.InflateException: Binary XML file line #8: Error inflating class fragment
Caused by: java.lang.NullPointerException
at com.krakert.tracker.ui.OverviewFragment.getBinding(OverviewFragment.kt:15)
at com.krakert.tracker.ui.OverviewFragment.onViewCreated(OverviewFragment.kt:28)
I would like some help here, setting the project up. Really new to Wear OS
Thanks!
Not sure how this can work and suspect this is where the NullPointerException comes from
private var _binding: FragmentOverviewBinding? = null
private val binding get() = _binding!!
compare to the example at https://developer.android.com/topic/libraries/view-binding#fragments
which sets _binding in onCreateView
I want to navigate to Profile Fragment, when the user wants to sign up. The LoginBottomSheetFragment is responsible to perform this navigation whenever it pops up from the bottom and user clicks on the button. The problem is that whenever I am trying to use findNavController I get the error:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.fjklabs.pkfinance, PID: 8711
java.lang.IllegalStateException: View android.widget.LinearLayout{32bc1d5 V.E...... ......ID 0,0-1328,935 #7f090188 app:id/rootLayout} does not have a NavController set
at androidx.navigation.Navigation.findNavController(Navigation.java:84)
at androidx.navigation.fragment.NavHostFragment.findNavController(NavHostFragment.java:118)
at androidx.navigation.fragment.FragmentKt.findNavController(Fragment.kt:29)
at com.fjklabs.pkfinance.fragment.LoginBottomDialogFragment$onCreateView$1.onClick(LoginBottomDialogFragment.kt:42)
at android.view.View.performClick(View.java:7125)
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 the current flow:
MainActivity -> Activity A -> Open BottomSheetFragment -> Navigate to Profile Fragment
This is what (some part of) my navigation xml looks like:
<navigation 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"
app:startDestination="#id/home">
<fragment
android:id="#+id/login_bottom_sheet"
android:name="LoginBottomDialogFragment"
tools:layout="#layout/fragment_login_bottom_dialog">
<action
android:id="#+id/navigate_to_profile"
app:destination="#id/profile"/>
</fragment>
<fragment
android:id="#+id/profile"
android:name="ProfileFragment"
android:label="Account info"
tools:layout="#layout/fragment_profile"/>
</navigation>
BottomSheetDialogFragment:
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val rootView = inflater.inflate(R.layout.fragment_login_bottom_dialog, container, false)
btnLogin = rootView.findViewById(R.id.signup_user)
btnLogin.setOnClickListener {
dismiss()
findNavController().navigate(LoginBottomDialogFragmentDirections.navigateToProfile())
}
root = rootView
return rootView
}
Activity A opens BottomSheetFragment:
fun showBottomDialogFragment() {
bottomDialogFragment.show(supportFragmentManager, "LOGIN_DIALOG_FRAGMENT")
}
Since the navigation is part of the MainActivity layout, The problem seems like Activity A does not have any access to NavController. How would get hold of NavController in such scenario?
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 1 year ago.
I have an app that has MainActivity but all the work is in the fragment.
I made the fragment layout the HomePage using JetPack navigation. and it worked. but when i added the recycler view it crashed.
the error was this:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.saheralsous.android, PID: 12418
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.saheralsous.android/com.saheralsous.android.MainActivity}: android.view.InflateException: Binary XML file line #20 in com.saheralsous.android:layout/activity_main: Binary XML file line #20 in com.saheralsous.android:layout/activity_main: Error inflating class fragment
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3449)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
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:2066)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Caused by: android.view.InflateException: Binary XML file line #20 in com.saheralsous.android:layout/activity_main: Binary XML file line #20 in com.saheralsous.android:layout/activity_main: Error inflating class fragment
Caused by: android.view.InflateException: Binary XML file line #20 in com.saheralsous.android:layout/activity_main: Error inflating class fragment
Caused by: java.lang.NullPointerException: null cannot be cast to non-null type androidx.recyclerview.widget.RecyclerView
at com.saheralsous.android.PhotoGalleryFragment.onCreateView(PhotoGalleryFragment.kt:45)
at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2963)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:518)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:282)
at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:112)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1647)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3128)
at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:3065)
at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:2988)
at androidx.fragment.app.FragmentStateManager.ensureInflatedView(FragmentStateManager.java:392)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:281)
at androidx.fragment.app.FragmentLayoutInflaterFactory.onCreateView(FragmentLayoutInflaterFactory.java:140)
at androidx.fragment.app.FragmentController.onCreateView(FragmentController.java:135)
at androidx.fragment.app.FragmentActivity.dispatchFragmentsOnCreateView(FragmentActivity.java:319)
at androidx.fragment.app.FragmentActivity.onCreateView(FragmentActivity.java:298)
at android.view.LayoutInflater.tryCreateView(LayoutInflater.java:1067)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:995)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:959)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:1121)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1082)
at android.view.LayoutInflater.inflate(LayoutInflater.java:680)
at android.view.LayoutInflater.inflate(LayoutInflater.java:532)
at android.view.LayoutInflater.inflate(LayoutInflater.java:479)
at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:699)
at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:195)
at com.saheralsous.android.MainActivity.onCreate(MainActivity.kt:9)
at android.app.Activity.performCreate(Activity.java:8000)
E/AndroidRuntime: at android.app.Activity.performCreate(Activity.java:7984)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
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:2066)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
I didn't add or change anything in the main activity
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
only in the activity_main i added the fragment for Navigation compnonent
<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=".MainActivity">
<fragment
android:id="#+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:defaultNavHost="true"
app:navGraph="#navigation/nav_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>
i initialize the recyclerview in the fragment this way:
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
/**
* PagingDataAdapter
*/
RecyclerViewPhotoAdapter = RecyclerViewPhotoAdapter()
/**
* Recycler View
*/
PhotoRecyclerView =
view?.findViewById(R.id.recyclerview_main) as RecyclerView
PhotoRecyclerView.layoutManager = LinearLayoutManager(context)
//linking adapter with recyclerview
PhotoRecyclerView.adapter = RecyclerViewPhotoAdapter
/**
* Adapter, Repository and viewmodel
*/
pagingAdapter = PhotoPaging(
(requireActivity().application as MyApplication).networkApi
)
repository = GalleryFlowRepositoryImpl(pagingAdapter)
viewModel = ViewModelProvider(this, ViewModelProviderFactory(
PhotoGalleryViewModel::class
){
PhotoGalleryViewModel(repository)
}).get(PhotoGalleryViewModel::class.java)
//observing data
observers()
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_photo_gallery, container, false)
}
fragment_photo_gallery layout is simply this
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".PhotoGalleryFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerview_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</FrameLayout>
In your onCreateView you access the view before inflating the layout.
At line:
PhotoRecyclerView = view?.findViewById(R.id.recyclerview_main) as RecyclerView
you try to retrieve the recyclerview_main in the view wich is null because at this point the layout is not inflated.
Then you force cast it into a RecyclerView (as RecyclerView instead of as? RecyclerView for optional cast) wich lead to a NullPointerExcepion.
I would recommand moving your code into onViewCreated method.
ok it's not a big problem you need to inflate before you use view
first, add this on the top of your onCreateView
val view = inflater.inflate(R.layout.fragment_photo_gallery, container, false)
then return view at the end
return view
hope my answer helped you
I found problem in your code.
You didn't inflate view before use RecyclerView.
PhotoRecyclerView =
view?.findViewById(R.id.recyclerview_main) as RecyclerView
In there, view should be null. because you didn't inflate view.
So to resolve your problem, there are two methods.
First, in onCreateView method you should inflate view before using.
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
var view = inflater.inflate(R.layout.fragment_photo_gallery, container, false)
/**
* PagingDataAdapter
*/
RecyclerViewPhotoAdapter = RecyclerViewPhotoAdapter()
/**
* Recycler View
*/
PhotoRecyclerView =
view?.findViewById(R.id.recyclerview_main) as RecyclerView
PhotoRecyclerView.layoutManager = LinearLayoutManager(context)
//linking adapter with recyclerview
PhotoRecyclerView.adapter = RecyclerViewPhotoAdapter
/**
* Adapter, Repository and viewmodel
*/
pagingAdapter = PhotoPaging(
(requireActivity().application as MyApplication).networkApi
)
repository = GalleryFlowRepositoryImpl(pagingAdapter)
viewModel = ViewModelProvider(this, ViewModelProviderFactory(
PhotoGalleryViewModel::class
){
PhotoGalleryViewModel(repository)
}).get(PhotoGalleryViewModel::class.java)
//observing data
observers()
// Inflate the layout for this fragment
return view
}
Or Second, you can use your code in onViewCreated method.
I'm competely new to Kotlin trying to build an app following a tutorial, but trying to navigate to fragment it completely crashes.
This what I got after I tried to navigate to the other fragment:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.application, PID: 10385
java.lang.IllegalArgumentException: No view found for id 0x7f08005a (com.example.application:id/container) for fragment Create{b25f2a9 (ffc51d9a-d9bb-425d-a264-1a68c77134fb) id=0x7f08005a}
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:875)
at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManagerImpl.java:1238)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:1303)
at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:439)
at androidx.fragment.app.FragmentManagerImpl.executeOps(FragmentManagerImpl.java:2079)
at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManagerImpl.java:1869)
at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManagerImpl.java:1824)
at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManagerImpl.java:1727)
at androidx.fragment.app.FragmentManagerImpl$2.run(FragmentManagerImpl.java:150)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
This how I try to navigate to the fragment.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val bottomNavigation: BottomNavigationView = findViewById(R.id.nav_view)
bottomNavigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener)
}
private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
when (item.itemId) {
R.id.menu_home -> {
val fragment_main = Main.newInstance()
openFragment(fragment_main)
return#OnNavigationItemSelectedListener true
}
R.id.menu_create -> {
val fragment_create = Create.newInstance()
openFragment(fragment_create)
return#OnNavigationItemSelectedListener true
}
R.id.menu_your -> {
val fragment_your_articles = YourArticles.newInstance()
openFragment(fragment_your_articles)
return#OnNavigationItemSelectedListener true
}
}
false
}
private fun openFragment(fragment: Fragment) {
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.container, fragment)
transaction.addToBackStack(null)
transaction.commit()
}
}
One of the Fragment class
class Create : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? =
inflater.inflate(R.layout.fragment_create, container, false)
companion object {
fun newInstance(): Create = Create()
}
}
I want to know what mistake did I made to cause the crash and how can I fix it.
This xml file of one of the fragment:
<?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="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/textView4"
android:layout_width="100dp"
android:layout_height="50dp"
android:layout_marginStart="150dp"
android:layout_marginLeft="150dp"
android:layout_marginTop="200dp"
android:text="#string/create_screen"
/>
</LinearLayout>
The id passed into FragmentTransaction.add(), in your case R.id.fragment_create, must be a child of the layout specified in setContentView().
For help: A view is a child of another view if it is declared inside of the parent view in the XML. ie. a TextView inside of a RelativeLayout is a child of the RelativeLayout
As I said I'm completely new to Kotlin and I'm still getting used to how and what must be displayed if I'm trying to use Fragment. I forgot that I need FrameLayout to my main_activity.xml
As I added FrameLayout in my main_activity.xml file it's started working as I wanted.
This line in your openFragment function
transaction.replace(R.id.container, fragment)
tells it to place the fragment in the ViewGroup with the ID "container". But your layout does not contain a ViewGroup with this ID. Check your activity_main.xml layout and make sure it has one with that ID.
I am working on a very simple sample app that uses ViewModel, coroutines and databinding.
Here the very simple classes used :
class MainFragment : Fragment() {
companion object {
fun newInstance() = MainFragment()
}
private val viewModel by viewModels<MainViewModel>()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val binding: MainFragmentBinding =
DataBindingUtil.inflate(inflater, R.layout.main_fragment, container, false)
binding.lifecycleOwner = viewLifecycleOwner
binding.model = viewModel
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel.loadData()
}
}
class MainViewModel : ViewModel() {
val txt1 = MutableLiveData<String>()
val txt2 = Transformations.map(txt1)
{
if (it == "test") R.string.yes else R.string.no
}
fun loadData() {
viewModelScope.launch(Dispatchers.IO)
{
delay(1000)
txt1.postValue("test")
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<layout>
<data>
<variable
name="model"
type="com.example.myapplication.ui.main.MainViewModel" />
</data>
<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/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.main.MainFragment">
<TextView
android:id="#+id/txt1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{model.txt1}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:id="#+id/txt2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{model.txt2}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
Unfortunately, this very simple app crashs with the following stacktrace :
java.lang.RuntimeException: Failed to call observer method
at androidx.lifecycle.ClassesInfoCache$MethodReference.invokeCallback(ClassesInfoCache.java:226)
at androidx.lifecycle.ClassesInfoCache$CallbackInfo.invokeMethodsForEvent(ClassesInfoCache.java:194)
at androidx.lifecycle.ClassesInfoCache$CallbackInfo.invokeCallbacks(ClassesInfoCache.java:185)
at androidx.lifecycle.ReflectiveGenericLifecycleObserver.onStateChanged(ReflectiveGenericLifecycleObserver.java:37)
at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:361)
at androidx.lifecycle.LifecycleRegistry.forwardPass(LifecycleRegistry.java:300)
at androidx.lifecycle.LifecycleRegistry.sync(LifecycleRegistry.java:339)
at androidx.lifecycle.LifecycleRegistry.moveToState(LifecycleRegistry.java:145)
at androidx.lifecycle.LifecycleRegistry.handleLifecycleEvent(LifecycleRegistry.java:131)
at androidx.fragment.app.FragmentViewLifecycleOwner.handleLifecycleEvent(FragmentViewLifecycleOwner.java:51)
at androidx.fragment.app.Fragment.performStart(Fragment.java:2737)
at androidx.fragment.app.FragmentStateManager.start(FragmentStateManager.java:355)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1192)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1354)
at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:1432)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1495)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2617)
at androidx.fragment.app.FragmentManager.dispatchStart(FragmentManager.java:2575)
at androidx.fragment.app.FragmentController.dispatchStart(FragmentController.java:258)
at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:550)
at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:178)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1391)
at android.app.Activity.performStart(Activity.java:7157)
at android.app.ActivityThread.handleStartActivity(ActivityThread.java:2937)
at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:180)
at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:165)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:142)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: android.content.res.Resources$NotFoundException: String resource ID #0x0
at android.content.res.Resources.getText(Resources.java:348)
at android.widget.TextView.setText(TextView.java:5831)
at com.example.myapplication.databinding.MainFragmentBindingImpl.executeBindings(MainFragmentBindingImpl.java:168)
at androidx.databinding.ViewDataBinding.executeBindingsInternal(ViewDataBinding.java:472)
at androidx.databinding.ViewDataBinding.executePendingBindings(ViewDataBinding.java:444)
at androidx.databinding.ViewDataBinding$OnStartListener.onStart(ViewDataBinding.java:1685)
at java.lang.reflect.Method.invoke(Native Method)
at androidx.lifecycle.ClassesInfoCache$MethodReference.invokeCallback(ClassesInfoCache.java:216)
at androidx.lifecycle.ClassesInfoCache$CallbackInfo.invokeMethodsForEvent(ClassesInfoCache.java:194)
at androidx.lifecycle.ClassesInfoCache$CallbackInfo.invokeCallbacks(ClassesInfoCache.java:185)
at androidx.lifecycle.ReflectiveGenericLifecycleObserver.onStateChanged(ReflectiveGenericLifecycleObserver.java:37)
at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:361)
at androidx.lifecycle.LifecycleRegistry.forwardPass(LifecycleRegistry.java:300)
at androidx.lifecycle.LifecycleRegistry.sync(LifecycleRegistry.java:339)
at androidx.lifecycle.LifecycleRegistry.moveToState(LifecycleRegistry.java:145)
at androidx.lifecycle.LifecycleRegistry.handleLifecycleEvent(LifecycleRegistry.java:131)
at androidx.fragment.app.FragmentViewLifecycleOwner.handleLifecycleEvent(FragmentViewLifecycleOwner.java:51)
at androidx.fragment.app.Fragment.performStart(Fragment.java:2737)
at androidx.fragment.app.FragmentStateManager.start(FragmentStateManager.java:355)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1192)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1354)
at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:1432)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1495)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2617)
at androidx.fragment.app.FragmentManager.dispatchStart(FragmentManager.java:2575)
at androidx.fragment.app.FragmentController.dispatchStart(FragmentController.java:258)
at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:550)
at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:178)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1391)
at android.app.Activity.performStart(Activity.java:7157)
at android.app.ActivityThread.handleStartActivity(ActivityThread.java:2937)
at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:180)
at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:165)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:142)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
The line 168 of the MainFragmentBindingImpl.java class is the following one:
this.txt2.setText(androidxDatabindingViewDataBindingSafeUnboxModelTxt2GetValue);
So, the issue is the Transformations.map(...). If I remove the binding of the txt2 attribute, everything works correctly.
How can I avoid this bug ?
Thank you for your help.
Set a #BindingAdapter for android:text that takes a resource id.
I think it attempts to set the integer initial value of 0, hence the ResourceNotFound. Check for this in your adapter. The value of the string resource id immediately changes from 0 to the correct value.
#JvmStatic
#BindingAdapter("android:text")
fun setTextResource(view: TextView, #StringRes resource: Int) {
Timber.d("resource id: $resource")
if (resource == 0) {
view.text = ""
} else {
view.setText(resource)
}
}