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)
}
}
Related
I am using data binding in my project but whenever i want to start a new activity from my current one, it throws an error. I tried all the methods i can find on stackoverflow but none of those are seem to be working for me.
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.app.erp, PID: 12624
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.app.erp/com.app.erp.teacher_view.ActivityAfterTeacherLoginNavigationTakeAttendance}: java.lang.NullPointerException: null cannot be cast to non-null type java.util.ArrayList<kotlin.String>{ kotlin.collections.TypeAliasesKt.ArrayList<kotlin.String> }
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3308)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3457)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
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:2044)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:224)
at android.app.ActivityThread.main(ActivityThread.java:7560)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
Caused by: java.lang.NullPointerException: null cannot be cast to non-null type java.util.ArrayList<kotlin.String>{ kotlin.collections.TypeAliasesKt.ArrayList<kotlin.String> }
at com.app.erp.teacher_view.ActivityAfterTeacherLoginNavigationTakeAttendance.onCreate(ActivityAfterTeacherLoginNavigationTakeAttendance.kt:86)
at android.app.Activity.performCreate(Activity.java:7894)
at android.app.Activity.performCreate(Activity.java:7881)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1307)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3283)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3457)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
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:2044)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:224)
at android.app.ActivityThread.main(ActivityThread.java:7560)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
My Activity -
class ActivityAfterTeacherLoginNavigation : AppCompatActivity() {
private val fragmentViewModel : ActivityAfterTeacherLoginNavigationViewModel by viewModels()
private val db = FirebaseFirestore.getInstance()
private lateinit var teacherAttendanceArrayListRecyclerView: ArrayList<FragmentTeacherAttendanceLogRecyclerViewDataClass>
private lateinit var binding: ActivityAfterTeacherLoginNavigationBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_after_teacher_login_navigation)
binding.addAttendance = this
teacherAttendanceArrayListRecyclerView = arrayListOf<FragmentTeacherAttendanceLogRecyclerViewDataClass>()
val navController = findNavController(R.id.fragmentContainerView)
val navHostFragment = supportFragmentManager.findFragmentById(R.id.fragmentContainerView)!!
val navigator = KeepStateNavigator(this, navHostFragment.childFragmentManager, R.id.fragmentContainerView)
navController.navigatorProvider += navigator
navController.setGraph(R.navigation.teacher_activity_bottom_navigation)
binding.bottomNavigationView.setupWithNavController(navController)
navController.addOnDestinationChangedListener { _, destination, _ ->
when ((destination as FragmentNavigator.Destination).className) {
FragmentTeacherAttendanceLog::class.qualifiedName -> {
binding.fab.show()
binding.fab.text = "Add Attendance"
}
else -> {
binding.fab.hide()
}
}
}
loadTeacherInfo()
loadBatchData()
getAttendanceData()
}
fun navigateToTakeAttendance(view: View) {
startActivity(Intent(this#ActivityAfterTeacherLoginNavigation, ActivityAfterTeacherLoginNavigationTakeAttendance::class.java))
}
My XML file -
<layout 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">
<data>
<variable
name="addAttendance"
type="com.app.erp.teacher_view.ActivityAfterTeacherLoginNavigation" />
</data>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/parentFrameLayout"
tools:context=".teacher_view.ActivityAfterTeacherLoginNavigation">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="#+id/fragmentContainerView"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="#+id/fab"
android:stateListAnimator="#null"
app:elevation="0dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:onClick="#{addAttendance::navigateToTakeAttendance}"
app:layout_anchor="#id/bottomNavigationView"
app:icon="#drawable/ic_baseline_post_add_24"
app:layout_anchorGravity="end"
android:translationY="-20sp"
android:layout_marginEnd="20sp"/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottomNavigationView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="0dp"
android:layout_gravity="bottom"
app:labelVisibilityMode="selected"
app:layout_behavior="#string/hide_bottom_view_on_scroll_behavior"
app:menu="#menu/teacher_activity_bottom_menu" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/secondaryFragmentContainerTeacher" />
</FrameLayout>
Let me know if any other information is required. I am new to Data binding and it's concepts so i apologize if my approach is not good.
The code of the activity i want to start
class ActivityAfterTeacherLoginNavigationTakeAttendance : AppCompatActivity() {
private val db = FirebaseFirestore.getInstance()
private val fragmentViewModel: ActivityAfterTeacherLoginNavigationTakeAttendanceViewModel by viewModels()
private lateinit var title: TextView
private lateinit var binding: ActivityAfterTeacherLoginNavigationTakeAttendanceBinding
private lateinit var tempArrayListSemesterInfo: ArrayList<String>
#SuppressLint("SetTextI18n")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_after_teacher_login_navigation_take_attendance)
binding.title.text = "Attendance Details"
binding.proceedBut.setOnClickListener {
checkInput()
}
supportFragmentManager.popBackStack()
binding.semesterSelect.setOnClickListener{
if(binding.batchSelect.text.toString().isBlank()){
binding.batchSelect.setError("Please select Batch first",null)
binding.batchSelect.requestFocus()
}
}
binding.dateSelect.setText(getCurrentDate(),null)
binding.timeSelect.setText(getCurrentTime(),null)
fragmentViewModel.teacherCodeData.value = intent.getStringExtra("teacherCodeTxt").toString()
binding.teacherCode.setText(intent.getStringExtra("teacherCodeTxt").toString(),null)
fragmentViewModel.teacherNameData.value = intent.getStringExtra("teacherTxt").toString()
binding.teacherSelect.setText(intent.getStringExtra("teacherTxt").toString(),null)
val batchArrayList: ArrayList<String> = intent.getStringArrayListExtra("batchTxt") as ArrayList<String>
val batchArrayAdapter = ArrayAdapter<String>(this,
R.layout.exposed_dropdown_menu_item_layout,batchArrayList)
binding.batchSelect.setAdapter(batchArrayAdapter)
val courseArrayList: ArrayList<String> = intent.getStringArrayListExtra("courseTxt") as ArrayList<String>
val courseArrayAdapter = ArrayAdapter<String>(this,
R.layout.exposed_dropdown_menu_item_layout,courseArrayList)
binding.courseSelect.setAdapter(courseArrayAdapter)
tempArrayListSemesterInfo = arrayListOf<String>()
binding.batchSelect.onItemClickListener = AdapterView.OnItemClickListener { parent, _, position, _ ->
if(binding.batchSelect.text.isNotEmpty()){
binding.batchSelect.error = null
}
binding.semesterSelect.text.clear()
tempArrayListSemesterInfo.clear()
val selectedItem = parent.getItemAtPosition(position).toString()
db.collection("BatchInfo").whereEqualTo("Name",selectedItem)
.addSnapshotListener(object: EventListener<QuerySnapshot> {
#SuppressLint("NotifyDataSetChanged")
override fun onEvent(value: QuerySnapshot?, error: FirebaseFirestoreException?) {
if(error != null){
Log.e("Firestore Error",error.message.toString())
return
}
for(dc : DocumentChange in value?.documentChanges!!){
if(dc.type == DocumentChange.Type.ADDED){
tempArrayListSemesterInfo.addAll(dc.document.data.getValue("Semester") as Collection<String>)
val addStudentSemesterSelectAdapter = ArrayAdapter(this#ActivityAfterTeacherLoginNavigationTakeAttendance,
R.layout.exposed_dropdown_menu_item_layout, tempArrayListSemesterInfo)
binding.semesterSelect.setAdapter(addStudentSemesterSelectAdapter)
}
break
}
}
})
}
binding.courseSelect.onItemClickListener = AdapterView.OnItemClickListener { parent, _, position, _ ->
if (binding.courseSelect.text.isNotEmpty()) {
binding.courseSelect.error = null
}
val selectedItem = parent.getItemAtPosition(position).toString()
db.collection("CourseInfo").whereEqualTo("CourseName",selectedItem).get()
.addOnCompleteListener { itAlt ->
if(itAlt.isSuccessful){
for (doc in itAlt.result!!){
binding.courseCode.setText(doc.data.getValue("CourseCode").toString(),null)
}
}
}
}
binding.proceedBut.setOnClickListener {
checkInput()
}
}
}
Inside the loop you are trying to read a value that might be null value?.documentChanges . So you must use safe cast operator
add ? after as
for(dc : DocumentChange in value?.documentChanges!!){
if(dc.type == DocumentChange.Type.ADDED){
tempArrayListSemesterInfo.addAll(dc.document.data.getValue("Semester") as? Collection<String>)
val addStudentSemesterSelectAdapter = ArrayAdapter(this#ActivityAfterTeacherLoginNavigationTakeAttendance,
R.layout.exposed_dropdown_menu_item_layout, tempArrayListSemesterInfo)
binding.semesterSelect.setAdapter(addStudentSemesterSelectAdapter)
}
break
}
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 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.
This is my first question on Stack Overflow, so apologies in advance if I'm asking in an improper way.
I'm trying to create a basic app in Kotlin, wherein I have a hamburger menu with some fragments in it. When the user clicks on the HomeFragment, I want to display a welcome message with his name (stored in a Shared Preferences object).
However, each time I click on the menu button to open the fragment, it crashes - even if I remove the whole username/shared prefs thing and just try to set some plain text.
Here is my HomeFragment.kt file:
package com.urmilshroff.kotlindemo
import android.content.Context
import android.net.Uri
import android.os.Bundle
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import kotlinx.android.synthetic.main.fragment_home.*
private const val ARG_PARAM1="param1"
private const val ARG_PARAM2="param2"
class HomeFragment:Fragment()
{
private var param1:String?=null
private var param2:String?=null
private var listener:OnFragmentInteractionListener?=null
override fun onCreate(savedInstanceState:Bundle?)
{
super.onCreate(savedInstanceState)
arguments?.let {
param1=it.getString(ARG_PARAM1)
param2=it.getString(ARG_PARAM2)
}
}
override fun onCreateView(inflater:LayoutInflater,container:ViewGroup?,
savedInstanceState:Bundle?):View?
{
super.onCreate(savedInstanceState)
val username=SharedPrefObj.getUsername(this.activity!!)
textViewHello.text="Hi there, $username!"
return inflater.inflate(R.layout.fragment_home,container,false)
}
fun onButtonPressed(uri:Uri)
{
listener?.onFragmentInteraction(uri)
}
override fun onAttach(context:Context)
{
super.onAttach(context)
if(context is OnFragmentInteractionListener)
{
listener=context
}
else
{
throw RuntimeException(context.toString()+" must implement OnFragmentInteractionListener")
}
}
override fun onDetach()
{
super.onDetach()
listener=null
}
interface OnFragmentInteractionListener
{
fun onFragmentInteraction(uri:Uri)
}
companion object
{
#JvmStatic
fun newInstance()=
HomeFragment().apply {
arguments=Bundle().apply {
putString(ARG_PARAM1,param1)
putString(ARG_PARAM2,param2)
}
}
}
}
My fragment_home.xml, just in case:
<?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"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".HomeFragment">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/textViewHello"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:fontFamily="monospace"
android:textAlignment="center"
android:textColor="#color/colorAccent"
android:textSize="30sp"
app:layout_constraintBottom_toTopOf="#+id/textViewDesc"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.993" />
<TextView
android:id="#+id/textViewDesc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="240dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:fontFamily="monospace"
android:text="#string/text_view_desc"
android:textAlignment="center"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.503"
app:layout_constraintStart_toStartOf="parent" />
</android.support.constraint.ConstraintLayout>
</FrameLayout>
Crash log:
09-17 00:19:24.968 25279-25279/com.urmilshroff.kotlindemo E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.urmilshroff.kotlindemo, PID: 25279
java.lang.IllegalStateException: textViewHello must not be null
at com.urmilshroff.kotlindemo.HomeFragment.onCreateView(HomeFragment.kt:37)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2346)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1428)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1759)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1827)
at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:797)
at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2596)
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2383)
at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2338)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2245)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:703)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
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)
It says that textViewHello must not be null, so I tried making it nullable yet it crashes. Not sure what's wrong. Any help is much appreciated, thanks!
textViewHello has not been initialized.
Initialise it like this:
val rootView = inflater.inflate(R.layout.fragment_home,container,false)
val textViewHello: TextView = rootView.findViewById(R.id.textViewHello) as TextView
Add the above line before setting text on textview
final onCreateView will look like this:
super.onCreate(savedInstanceState)
val rootView = inflater.inflate(R.layout.fragment_home,container,false)
val username=SharedPrefObj.getUsername(this.activity!!)
val textViewHello: TextView = rootView.findViewById(R.id.textViewHello) as TextView
textViewHello.text="Hi there, $username!"
return rootView;
You are using Kotlin Android Extentions in your project, so no need to call findViewById method anymore.
All you need to do is change your code to:
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
super.onCreate(savedInstanceState)
return inflater.inflate(R.layout.fragment_home, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val username = SharedPrefObj.getUsername(this.activity!!)
textViewHello.text = "Hi there, $username!"
}
put below line in onViewCreated method. You need to override that method.
textViewHello.text="Hi there, $username!"
this will set the textview after it has been initiated in onCreateView
You need use it in onViewCreated.
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.qr_my_fragment, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
init()
}
private fun init() {
setQRCode()
initToolbar()
clickEvents()
}
You are trying to call method setText, but your TextView object actually is null. You need to initialize.
Before set text, you should make some step.
1. Inflate view in variable
val view = inflater.inflate(R.layout.fragment_home,container,false)
2. Find and connect xml object with class variable
val textView: TextView = view.findViewById(R.id.textViewHello)
3. Now, you can call setText
textView.setText("Example text")
Just modify your onCreateView method
val view = inflater.inflate(R.layout.fragment_home,container,false)
val textView: TextView = view.findViewById(R.id.textViewHello)
textView.setText("Example text")