Lateinit property viewModel has not been initialized - android

I initialized viewModel with this line viewModel = (activity as NewsActivity).viewModel in BreakingNewsFragment but, recived below error.
How i can fix this problem?! thanks for your help
BreakingNewsFragment
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.View
import com.example.simplenewsapp.R
import com.example.simplenewsapp.main.MainViewModel
import com.example.simplenewsapp.NewsActivity
import com.example.simplenewsapp.adapter.NewsRecyclerViewAdapter
import kotlinx.android.synthetic.main.fragment_breaking_news.*
class BreakingNewsFragment : Fragment(R.layout.fragment_breaking_news) {
lateinit var viewModel: MainViewModel
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel = (activity as NewsActivity).viewModel
....
NewsActivity
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.findNavController
import androidx.navigation.ui.setupWithNavController
import com.example.simplenewsapp.data.local.ArticleDatabase
import com.example.simplenewsapp.main.MainRepository
import com.example.simplenewsapp.main.MainViewModel
import com.example.simplenewsapp.main.MainViewModelProviderFactory
import kotlinx.android.synthetic.main.activity_news.*
class NewsActivity : AppCompatActivity() {
lateinit var viewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_news)
val newsRepository = MainRepository(ArticleDatabase(this))
val mainViewModelProviderFactory = MainViewModelProviderFactory(newsRepository)
viewModel =
ViewModelProvider(this, mainViewModelProviderFactory).get(MainViewModel::class.java)
bottomNavigationView.setupWithNavController(newsNavHostFragment.findNavController())
}
}
MainViewModelProviderFactory
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
class MainViewModelProviderFactory(val mainRepository:MainRepository): ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return MainViewModel(mainRepository) as T
}
}
MainViewModel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.simplenewsapp.data.local.models.NewsResponse
import com.example.simplenewsapp.util.Resource
import kotlinx.coroutines.launch
import retrofit2.Response
class MainViewModel(
val newsRepository: MainRepository
) : ViewModel() {
val breakingNews: MutableLiveData<Resource<NewsResponse>> = MutableLiveData()
var breakingNewsPage = 1
init {
getBreakingNews("us")
}
fun getBreakingNews(countyCode: String) = viewModelScope.launch {
breakingNews.postValue(Resource.Loading())
val response = newsRepository.getBreakingNews(countyCode, breakingNewsPage)
breakingNews.postValue(handleBreakingNewsResponse(response))
}
private fun handleBreakingNewsResponse(response: Response<NewsResponse>): Resource<NewsResponse> {
if (response.isSuccessful) {
response.body()?.let { resultResponse ->
return Resource.Success(resultResponse)
}
}
return Resource.Error(response.message())
}
}
Error:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.simplenewsapp, PID: 4455
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.simplenewsapp/com.example.simplenewsapp.NewsActivity}: android.view.InflateException: Binary XML file line #17: Binary XML file line #17: Error inflating class fragment
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2913)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
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.view.InflateException: Binary XML file line #17: Binary XML file line #17: Error inflating class fragment
Caused by: android.view.InflateException: Binary XML file line #17: Error inflating class fragment
Caused by: kotlin.UninitializedPropertyAccessException: lateinit property viewModel has not been initialized
at com.example.simplenewsapp.NewsActivity.getViewModel(NewsActivity.kt:16)
at com.example.simplenewsapp.ui.fragments.BreakingNewsFragment.onViewCreated(BreakingNewsFragment.kt:29)
at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:2974)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:543)
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:1636)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3112)
at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:3049)
at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:2975)
at androidx.fragment.app.FragmentStateManager.ensureInflatedView(FragmentStateManager.java:389)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:281)
at androidx.fragment.app.FragmentLayoutInflaterFactory.onCreateView(FragmentLayoutInflaterFactory.java:141)
at androidx.fragment.app.FragmentController.onCreateView(FragmentController.java:135)
at androidx.fragment.app.FragmentActivity.dispatchFragmentsOnCreateView(FragmentActivity.java:313)
at androidx.fragment.app.FragmentActivity.onCreateView(FragmentActivity.java:292)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:780)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:730)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:863)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:866)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824)
at android.view.LayoutInflater.inflate(LayoutInflater.java:515)
at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
at android.view.LayoutInflater.inflate(LayoutInflater.java:374)
at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:696)
at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:170)
at com.example.simplenewsapp.NewsActivity.onCreate(NewsActivity.kt:20)
at android.app.Activity.performCreate(Activity.java:7136)
at android.app.Activity.performCreate(Activity.java:7127)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
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)
I/Process: Sending signal. PID: 4455 SIG: 9

Firstly why you are using same View Model for fragment and activity ?
This approach is incorrect and may lead to inconsistent data and memory leaks.
Ideally fragment and activity should have their own independent View Model.
For example:
a) NewsActivity and NewsViewModel
b) BreakingNewsFragment and BreakingNewsViewModel
This separates the code by following the Separation of concerns principle and you will get benefit from this as your application logic grows.
And If you are looking for shared behavior/data, please used Shared View Model.
Secondly, instead of using the View Model from NewsActivity
you should initialize it completely in BreakingNewsFragment, the way you did in NewsActivity.
// Add below code either in your fragment or activity.
val newsRepository = MainRepository(ArticleDatabase(this))
val mainViewModelProviderFactory = MainViewModelProviderFactory(newsRepository)
viewModel = ViewModelProvider(this, mainViewModelProviderFactory).get(MainViewModel::class.java)

I know it's late but I'm happy to find the solution:
The problem was fragment tag of xml.
I changed the fragment tag to androidx.fragment.app.FragmentContainerView.
and initializing the fragmentcontentview and setting up nav controller:
val navHostFragment= supportFragmentManager.findFragmentById(R.id.newsNavHostFrag) as NavHostFragment
val navController= navHostFragment.navController
bottomNavigationView.setupWithNavController(navController)

Use this dependency instead:
implementation 'androidx.appcompat:appcompat:1.2.0'
and use this version only.
I used to use implementation 'androidx.appcompat:appcompat:1.3.1', and that creates the same error as you are facing.
Try once and use implementation 'androidx.appcompat:appcompat:1.2.0' dependency and exact the same version - that's what worked for me.

If you are using fragment like this:-
<FrameLayout
android:id="#+id/flFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="#+id/bottomNavigationView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<fragment
android:id="#+id/newsNavHostFragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="#navigation/news_nav_graph" />
</FrameLayout>
then you have to change your appcompat dependency version 1.3.1 to 1.2.0 like this
implementation 'androidx.appcompat:appcompat:1.2.0'
but if you are using latest dependency version i.e 1.3.1 then you have to use
<androidx.fragment.app.FragmentContainerView
android:id="#+id/newsNavHostFrag"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="#navigation/news_nav_graph"/>
and in MainActivity.kt
change this :-
bottomNavigationView.setupWithNavController(newsNavHostFragment.findNavController())
to this:-
val navHostFragment= supportFragmentManager.findFragmentById(R.id.newsNavHostFrag) as NavHostFragment
val navController= navHostFragment.navController
bottomNavigationView.setupWithNavController(navController)

Use below line instead of lateinit var viewModel: MainViewModel
private val viewModel:MainViewModel by activityViewModels()
Also , if you can't import it check for this dependency in app level build.gradle
implementation 'androidx.fragment:fragment-ktx:1.1.0'
and remove this line : viewModel = (activity as NewsActivity).viewModel

For solving this error, you have to put this code in your activity as well as in your fragment both
in Newsactivity:-
val newsResporiaty = NewsResporiaty(ArticleDatabase(requireContext()))
val viewModelFactory = NewsViewModelProviderFactory(newsResporiaty)
viewModel = ViewModelProvider(this,viewModelFactory).get(NewsViewModel::class.java)
And also your in fragmets:-
val newsResporiaty = NewsResporiaty(ArticleDatabase(requireContext()))
val viewModelFactory = NewsViewModelProviderFactory(newsResporiaty)
viewModel = ViewModelProvider(this,viewModelFactory).get(NewsViewModel::class.java)
This worked for me.

Related

Navigation.findNavController() in Fragment does not work properly

I'm trying develope single-activity application using the navigation to corresponding fragment from my home fragment under certain conditions (see my code fragment below). But when I start application with the condition isLoggedIn == true, an exception appears:
2022-05-01 17:42:22.888 14974-14974/com.example.shercofaqapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.shercofaqapp, PID: 14974
java.lang.IllegalStateException: Fragment LoginFragment{d69320f} (2bebfc01-ce4e-435e-be4f-821b5d142eb8 id=0x7f0a0096) did not return a View from onCreateView() or this was called before onCreateView().
at androidx.fragment.app.Fragment.requireView(Fragment.java:2008)
at com.example.shercofaqapp.view.LoginFragment.onCreateView(LoginFragment.kt:47)
at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2995)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:523)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261)
at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:113)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1374)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2841)
at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:2777)
at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3020)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:551)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261)
at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:113)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1374)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2841)
at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:2784)
at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:262)
at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:478)
at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:246)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1425)
at android.app.Activity.performStart(Activity.java:7825)
at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3294)
at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:221)
at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:201)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:173)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
at android.os.Handler.dispatchMessage(Handler.java:107)
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 a fragment of my code:
package com.example.shercofaqapp.view
import android.content.Context
import android.os.Bundle
import android.text.TextUtils
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.databinding.DataBindingUtil
import androidx.navigation.Navigation
import com.example.shercofaqapp.R
import com.example.shercofaqapp.databinding.FragmentLoginBinding
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.FirebaseUser
import kotlin.properties.Delegates
class LoginFragment : Fragment() {
lateinit var binding: FragmentLoginBinding
private var isLoggedIn by Delegates.notNull<Boolean>()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val sharedPref = requireActivity()
.getSharedPreferences("MyPreferences", Context.MODE_PRIVATE)
val editor = sharedPref.edit()
var isLoggingIn = false
binding = DataBindingUtil.inflate(
inflater, R.layout.fragment_login, container, false)
binding.apply {
//Log in / sign up logic
isLoggedIn = sharedPref.getBoolean("isLoggedIn", false)
if (isLoggedIn) {
Navigation.findNavController(requireView())
.navigate(R.id.action_loginFragment_to_garageFragment)
}
}
return binding.root
}
}
The question is: how can I get view for Navigation before onCreateView() return it?
I tried to use this solution, but I don't understand what argument I should pass to .findNavController(...) in my case.
P.S. NavHostFragment is in MainActivity:
<?xml version="1.0" encoding="utf-8"?>
<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"
tools:context=".MainActivity">
<androidx.fragment.app.FragmentContainerView
android:id="#+id/containerView"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="#navigation/nav_graph" />
</layout>
As per the Navigate to a destination documentation, you should use the findNavController() Kotlin extension on Fragment, which is a convenience wrapper around calling NavHostFragment.findNavController(this):
binding.apply {
//Log in / sign up logic
isLoggedIn = sharedPref.getBoolean("isLoggedIn", false)
if (isLoggedIn) {
// Make sure to:
// 1. Add a dependency on navigation-fragment-ktx in your build.gradle
// 2. import androidx.navigation.fragment.findNavController
findNavController()
.navigate(R.id.action_loginFragment_to_garageFragment)
}
}
findNavController(requireActivity())
.navigate(R.id.action_loginFragment_to_garageFragment)
use this code of line, I think it is helpful for you
Edit : If you are using it in fragment then,
Navigation.findNavController(getView()).navigate(R.id.action_loginFragment_to_garageFragment)

Hilt Doesn't Inject a Scoped ViewModel

I'm trying to inject a dependency into a navigation graph scoped ViewModel
This is my app :
#HiltAndroidApp
class App : Application()
The activity hosting my fragment :
#AndroidEntryPoint
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findNavController(R.id.nav_host_fragment).navigate(R.id.main_graph)
}
}
My navigation graph :
<?xml version="1.0" encoding="utf-8"?>
<navigation
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/main_graph"
app:startDestination="#id/mainFragment">
<fragment
android:id="#+id/mainFragment"
android:name="com.example.hilt.MainFragment" />
</navigation>
The object I'm going to inject into my ViewModel :
class Repo #Inject constructor()
My ViewModel :
#HiltViewModel
class MainViewModel #Inject constructor(
val repo: Repo,
application: Application
) : AndroidViewModel(application) {
fun test(){}
}
The fragment into which I inject the view model :
#AndroidEntryPoint
class MainFragment : Fragment() {
val viewModel: MainViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel.test()
}
}
Now at this point everything is working properly, but as soon as I try to scope the VM using this :
#AndroidEntryPoint
class MainFragment : Fragment() {
val viewModel: MainViewModel by navGraphViewModels(R.id.main_graph)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel.test()
}
}
The app fails to create my ViewModel and crashes leaving this stacktrace :
Caused by: java.lang.RuntimeException: Cannot create an instance of class com.example.hilt.MainViewModel
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:269)
at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.java:112)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:185)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)
at androidx.lifecycle.ViewModelLazy.getValue(ViewModelProvider.kt:54)
at androidx.lifecycle.ViewModelLazy.getValue(ViewModelProvider.kt:41)
at com.example.hilt.MainFragment.getViewModel(Unknown Source:2)
at com.example.hilt.MainFragment.onCreate(MainFragment.kt:17)
at androidx.fragment.app.Fragment.performCreate(Fragment.java:2936)
at androidx.fragment.app.FragmentStateManager.create(FragmentStateManager.java:472)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:278)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:2177)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:2094)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1990)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3122)
at androidx.fragment.app.FragmentManager.dispatchCreate(FragmentManager.java:3045)
at androidx.fragment.app.Fragment.onCreate(Fragment.java:1867)
at androidx.navigation.fragment.NavHostFragment.onCreate(NavHostFragment.java:264)
at androidx.fragment.app.Fragment.performCreate(Fragment.java:2936)
at androidx.fragment.app.FragmentStateManager.create(FragmentStateManager.java:472)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:278)
at androidx.fragment.app.FragmentLayoutInflaterFactory.onCreateView(FragmentLayoutInflaterFactory.java:141)
at androidx.fragment.app.FragmentController.onCreateView(FragmentController.java:135)
at androidx.fragment.app.FragmentActivity.dispatchFragmentsOnCreateView(FragmentActivity.java:313)
at androidx.fragment.app.FragmentActivity.onCreateView(FragmentActivity.java:292)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:780)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:730)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:863)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824)
at android.view.LayoutInflater.inflate(LayoutInflater.java:515)
at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
at android.view.LayoutInflater.inflate(LayoutInflater.java:374)
at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:696)
at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:170)
Clearly the by navGraphViewModels shorthand is not using the right VM Factory and I'm a bit at a loss here.
Use hiltNavGraphViewModels from androidx.hilt:hilt-navigation-fragment instead of navGraphViewModels
https://developer.android.com/training/dependency-injection/hilt-jetpack#viewmodel-navigation

Multiple exceptions: Unable to start activity, Unable to instantiate fragment, Error inflating class

I'm brand new to Kotlin and I'm following a tutorial. Running my app causes it to crash on runtime. I have three fragments, and one main activity, in a bottom navigation bar app. My goal is really just to run the app successfully so I can try out Room databases, data binding and such concepts. I searched for possible reasons why it doesn't work with me but no luck. This is the current full error message:
2021-02-27 14:58:23.967 23883-23883/com.jwanhsulaiman.talktag E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.jwanhsulaiman.talktag, PID: 23883
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.jwanhsulaiman.talktag/com.jwanhsulaiman.talktag.MainActivity}: android.view.InflateException: Binary XML file line #21: Binary XML file line #21: Error inflating class androidx.fragment.app.FragmentContainerView
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2919)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3054)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1814)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:280)
at android.app.ActivityThread.main(ActivityThread.java:6706)
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.view.InflateException: Binary XML file line #21: Binary XML file line #21: Error inflating class androidx.fragment.app.FragmentContainerView
Caused by: android.view.InflateException: Binary XML file line #21: Error inflating class androidx.fragment.app.FragmentContainerView
Caused by: androidx.fragment.app.Fragment$InstantiationException: Unable to instantiate fragment com.jwanhsulaiman.talktag.ui.home.HomeFragment: could not find Fragment constructor
at androidx.fragment.app.Fragment.instantiate(Fragment.java:625)
at androidx.fragment.app.FragmentContainer.instantiate(FragmentContainer.java:57)
at androidx.fragment.app.FragmentManager$3.instantiate(FragmentManager.java:483)
at androidx.navigation.fragment.FragmentNavigator.instantiateFragment(FragmentNavigator.java:132)
at androidx.navigation.fragment.FragmentNavigator.navigate(FragmentNavigator.java:162)
at androidx.navigation.fragment.FragmentNavigator.navigate(FragmentNavigator.java:58)
at androidx.navigation.NavGraphNavigator.navigate(NavGraphNavigator.java:71)
at androidx.navigation.NavGraphNavigator.navigate(NavGraphNavigator.java:28)
at androidx.navigation.NavController.navigate(NavController.java:1059)
at androidx.navigation.NavController.onGraphCreated(NavController.java:639)
at androidx.navigation.NavController.setGraph(NavController.java:592)
at androidx.navigation.NavController.setGraph(NavController.java:557)
at androidx.navigation.NavController.setGraph(NavController.java:539)
at androidx.navigation.fragment.NavHostFragment.onCreate(NavHostFragment.java:248)
at androidx.fragment.app.Fragment.performCreate(Fragment.java:2936)
at androidx.fragment.app.FragmentStateManager.create(FragmentStateManager.java:472)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:278)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:2177)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:2094)
at androidx.fragment.app.FragmentManager.execSingleAction(FragmentManager.java:1959)
at androidx.fragment.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:311)
at androidx.fragment.app.FragmentContainerView.<init>(FragmentContainerView.java:176)
at androidx.fragment.app.FragmentLayoutInflaterFactory.onCreateView(FragmentLayoutInflaterFactory.java:52)
at androidx.fragment.app.FragmentController.onCreateView(FragmentController.java:135)
at androidx.fragment.app.FragmentActivity.dispatchFragmentsOnCreateView(FragmentActivity.java:313)
at androidx.fragment.app.FragmentActivity.onCreateView(FragmentActivity.java:292)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:780)
2021-02-27 14:58:23.971 23883-23883/com.jwanhsulaiman.talktag E/AndroidRuntime: at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:730)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:863)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824)
at android.view.LayoutInflater.inflate(LayoutInflater.java:515)
at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
at android.view.LayoutInflater.inflate(LayoutInflater.java:374)
at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:696)
at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:170)
at com.jwanhsulaiman.talktag.MainActivity.onCreate(MainActivity.kt:15)
at android.app.Activity.performCreate(Activity.java:7136)
at android.app.Activity.performCreate(Activity.java:7127)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1272)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2899)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3054)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1814)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:280)
at android.app.ActivityThread.main(ActivityThread.java:6706)
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: java.lang.NoSuchMethodException: <init> []
at java.lang.Class.getConstructor0(Class.java:2327)
at java.lang.Class.getConstructor(Class.java:1725)
at androidx.fragment.app.Fragment.instantiate(Fragment.java:610)
... 50 more
I've tried changing the XML file on line 21 (as per the error) from fragment to androidx.fragment.app.FragmentContainerView (as per Android Studio's suggestion upon hovering with mouse. I've tried adding dependencies but nothing seems to change to the better. I'll provide how my code looks like.
MainActivity.kt (errors says it crashes on setContentView(R.layout.activity_main))
package com.jwanhsulaiman.talktag
import android.os.Bundle
import com.google.android.material.bottomnavigation.BottomNavigationView
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val navView: BottomNavigationView = findViewById(R.id.nav_view)
val navController = findNavController(R.id.nav_host_fragment)
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
val appBarConfiguration = AppBarConfiguration(setOf(
R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_notifications))
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
}
}
activity_main.xml
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="?attr/actionBarSize">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/nav_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:background="?android:attr/windowBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="#menu/bottom_nav_menu" />
<androidx.fragment.app.FragmentContainerView
android:id="#+id/nav_host_fragment"
class = "androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="#id/nav_view"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="#navigation/mobile_navigation" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
And the full snippet of HomeFragment in case it's related
package com.jwanhsulaiman.talktag.ui.home
import android.content.Context
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.jwanhsulaiman.talktag.R
import com.jwanhsulaiman.talktag.database.VocabData
import com.jwanhsulaiman.talktag.database.VocabRepository
import com.jwanhsulaiman.talktag.databinding.FragmentHomeBinding
class HomeFragment(val applicationContext: Context) : Fragment() {
private lateinit var homeViewModel: HomeViewModel
private lateinit var binding: FragmentHomeBinding
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
homeViewModel =
ViewModelProvider(this).get(HomeViewModel::class.java)
val root = inflater.inflate(R.layout.fragment_home, container, false)
val textView: TextView = root.findViewById(R.id.text_home)
homeViewModel.text.observe(viewLifecycleOwner, Observer {
textView.text = it
})
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_home, container, false)
val dao = VocabData.getInstance(this).VocabDao
val repository = VocabRepository(dao)
val factory = HomeViewModelFactory(repository)
homeViewModel = ViewModelProvider(this, factory).get(HomeViewModel::class.java)
binding.myViewModel = homeViewModel
binding.lifecycleOwner = this
displayVocabList()
return binding.root
}
private fun displayVocabList() {
homeViewModel.vocabs.observe(viewLifecycleOwner, Observer {
Log.i("MYTAG", it.toString())
})
}
}
Thanks for any insights!
Caused by: java.lang.NoSuchMethodException: <init> []
Remove the constructor from HomeFragment, for two reasons:
It will not work, as the fragment system requires a public zero-argument constructor
You do not need to pass in a Context, as once your fragment is attached to an activity, you can call requireContext() to retrieve a Context to use (and can reference applicationContext on it if you really do need the Application)

SwipeRefreshLayout Attempt to invoke virtual method on a null object reference [duplicate]

This question already has answers here:
findViewByID returns null
(33 answers)
NullPointerException when trying to access views in a Kotlin fragment
(9 answers)
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 2 years ago.
I am new to android development. I have only been doing it for about a month now so I apologize if this is a simple question.
I am keep getting the following error when trying to run my app
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.swiperefreshlayout.widget.SwipeRefreshLayout.setOnRefreshListener(androidx.swiperefreshlayout.widget.SwipeRefreshLayout$OnRefreshListener)' on a null object reference
at edu.cogswell.tn.prism.MainActivity.onCreate(MainActivity.kt:54)
at android.app.Activity.performCreate(Activity.java:7136)
at android.app.Activity.performCreate(Activity.java:7127)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048) 
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) 
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) 
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) 
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) 
Here is my code
package (package name)
import android.app.AlertDialog
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.gson.Gson
import edu.cogswell.tn.prism.`interface`.NewsService
import edu.cogswell.tn.prism.adapter.viewHolder.ListSourceAdapter
import edu.cogswell.tn.prism.common.Common
import edu.cogswell.tn.prism.modle.WebSite
import io.paperdb.Paper
import kotlinx.android.synthetic.main.fragment_central.*
import retrofit2.Call
import retrofit2.Response
import javax.security.auth.callback.Callback
class MainActivity : AppCompatActivity() {
lateinit var layoutManager: LinearLayoutManager
lateinit var myService: NewsService
lateinit var adapter: ListSourceAdapter
lateinit var dialog: AlertDialog
var mSwipeRefreshLayout: SwipeRefreshLayout? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val bottomNavigationView = findViewById<BottomNavigationView>(R.id.bottomNaigationView)
val navController = findNavController(R.id.fragment)
val appBarConfiguration = AppBarConfiguration(
setOf(
R.id.central,
R.id.leftWing,
R.id.rightWing
)
)
setupActionBarWithNavController(navController, appBarConfiguration)
bottomNavigationView.setupWithNavController(navController)
Paper.init(this)
myService = Common.newsService
swipe_to_refresh_centreal.setOnRefreshListener {
loadWebSiteSource(true)
}
recycler_view_source_news_central.setHasFixedSize(true)
layoutManager = LinearLayoutManager(this)
recycler_view_source_news_central.layoutManager = layoutManager
//dialog = SpotsDialog.Builder().setContext(this).build()
loadWebSiteSource(false)
}
private fun loadWebSiteSource(isRefresh: Boolean) {
if(!isRefresh){
val cache = Paper.book().read<String>("cache")
if(cache != null && !cache.isBlank() && cache != "null"){
val website = Gson().fromJson<WebSite>(cache, WebSite::class.java)
adapter = ListSourceAdapter(baseContext, website)
adapter.notifyDataSetChanged()
recycler_view_source_news_central.adapter = adapter
}
else{
dialog.show()
myService.sources.enqueue(object:retrofit2.Callback<WebSite>{
override fun onResponse(call: Call<WebSite>, response: Response<WebSite>) {
adapter = ListSourceAdapter(baseContext,response!!.body()!!)
adapter.notifyDataSetChanged()
recycler_view_source_news_central.adapter = adapter
Paper.book().write("cache", Gson().toJson(response!!.body()!!))
dialog.dismiss()
}
override fun onFailure(call: Call<WebSite>, t: Throwable) {
Toast.makeText(baseContext,"Failed",Toast.LENGTH_SHORT).show()
}
})
}
}
else{
swipe_to_refresh_centreal.isRefreshing = true
myService.sources.enqueue(object:retrofit2.Callback<WebSite>{
override fun onResponse(call: Call<WebSite>, response: Response<WebSite>) {
adapter = ListSourceAdapter(baseContext,response!!.body()!!)
adapter.notifyDataSetChanged()
recycler_view_source_news_central.adapter = adapter
Paper.book().write("cache", Gson().toJson(response!!.body()!!))
swipe_to_refresh_centreal.isRefreshing=false
}
override fun onFailure(call: Call<WebSite>, t: Throwable) {
Toast.makeText(baseContext,"Failed",Toast.LENGTH_SHORT).show()
}
})
}
}
}
Here is the xml code
<?xml version="1.0" encoding="utf-8"?>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
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/swipe_to_refresh_centreal"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Central">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view_source_news_central"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp" />
</RelativeLayout>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
Not too sure why I keep getting this error. I am using this tutorial https://www.youtube.com/watch?v=mvVcqzJYAbY
For reference.
Thank you in advance.
I see that you use kotlin synthetic properties here. It's deprecated. So I recommend using any other instrument instead. Even findViewById is better in my opinion.
So what's wrong here. It's an often issue related to kotlin synthetic properties - wrong imports.
Look, you do all actions in an activity, but imported
import kotlinx.android.synthetic.main.fragment_central.*
So this line import view from layout named fragment_central. But you inflated activity_main instead. So this view simply does not exist here.
You are importing wrong layout. Can you try this. Pass your main activity layout in import section and remove the swiperefresh layout from import as well as from variable declaratiion.
import kotlinx.android.synthetic.main.your_layout.*

null object reference error on Synthetic Binding from within Class

I'm a beginner with Android Studio and Kotlin. I get the following error when trying to change the text of a TextView using Synthetic Binding from within my class.
Unable to start activity ComponentInfo{com.oppenheimer.myapplication/com.oppenheimer.myapplication.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.pm.ApplicationInfo android.content.Context.getApplicationInfo()' on a null object reference
The code up to "Some other text" works but when I try with "Very new phrase" from within the class it crashes. It seems to be a common error but I'm not finding other posts that match my issue.
Here is my code
activity_main.xml
<?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">
<TextView
android:id="#+id/MyText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.kt
package com.oppenheimer.myapplication
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
MyText.text = "Some other text"
val myClass = MyClass()
myClass.MyFunction()
}
}
MyClass.kt
package com.oppenheimer.myapplication
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
class MyClass : AppCompatActivity() {
fun MyFunction () {
MyText.text = "Very new phrase"
}
}
Full Error
2020-05-02 13:13:50.784 3632-3632/com.oppenheimer.myapplication E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.oppenheimer.myapplication, PID: 3632
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.oppenheimer.myapplication/com.oppenheimer.myapplication.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.pm.ApplicationInfo android.content.Context.getApplicationInfo()' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3270)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
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:2016)
at android.os.Handler.dispatchMessage(Handler.java:107)
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)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.pm.ApplicationInfo android.content.Context.getApplicationInfo()' on a null object reference
at android.content.ContextWrapper.getApplicationInfo(ContextWrapper.java:163)
at android.view.ContextThemeWrapper.getTheme(ContextThemeWrapper.java:174)
at android.content.Context.obtainStyledAttributes(Context.java:738)
at androidx.appcompat.app.AppCompatDelegateImpl.createSubDecor(AppCompatDelegateImpl.java:692)
at androidx.appcompat.app.AppCompatDelegateImpl.ensureSubDecor(AppCompatDelegateImpl.java:659)
at androidx.appcompat.app.AppCompatDelegateImpl.findViewById(AppCompatDelegateImpl.java:479)
at androidx.appcompat.app.AppCompatActivity.findViewById(AppCompatActivity.java:214)
at com.oppenheimer.myapplication.MyClass._$_findCachedViewById(Unknown Source:25)
at com.oppenheimer.myapplication.MyClass.MyFunction(MyClass.kt:10)
at com.oppenheimer.myapplication.MainActivity.onCreate(MainActivity.kt:18)
at android.app.Activity.performCreate(Activity.java:7802)
at android.app.Activity.performCreate(Activity.java:7791)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409) 
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:2016) 
at android.os.Handler.dispatchMessage(Handler.java:107) 
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) 
How do I change the layout from within a class? What is the "right" way to do this? Should I Pass the TextView into the class?
Thanks
Generally speaking, you should not be trying to access a layout item from within another class, which is why you get an error.
Move it to the MainActivty's onCreate() function:
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
MyText.text = "Some other text"
val myClass = MyClass()
myClass.MyFunction()
MyText.text = "Very new phrase"
}
}
MyClass.kt
class MyClass : AppCompatActivity() {
fun MyFunction () {
}
}
If you really need to, you could access MyText and alter its value by passing a reference of it to MyClass and to MyFunction() as a parameter.
MainActivity.kt
package com.oppenheimer.myapplication
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
MyText.text = "Some other text"
val textView = findViewById<TextView>(R.id.MyText)
val myClass = MyClass(textView)
myClass.MyFunction(textView)
}
}
MyClass.kt
package com.oppenheimer.myapplication
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
class MyClass(textView: TextView) : AppCompatActivity() {
fun MyFunction (textView: TextView) {
textView.text = "Very new phrase"
}
}
Please note also that following naming conventions is good software practice and therefore all function names should start with a small letter, myFunction().

Categories

Resources