I have this code:
class SignInActivity {
private lateinit var binding: SingInBinding
fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = SingInBinding.inflate(layoutInflater)
setContentView(binding.root)
} // Start GameActivity
}
But I have errors in onCreate, layoutInflater, and setContentView: unresolved reference.
How can I fix it?
I want to fix the problem.
You are not extending any Activity class, you should do something like
class SignInActivity : ComponentActivity() {
...
}
Related
The code I wrote is not working because viewbinding is not suitable. I got some help from my friend but I still couldn't do the application please help me my application is interrupted
/*MainActivity*/
class MainActivity : AppCompatActivity() {
private var _binding: ActivityMainBinding?=null//
private val binding
get()=_binding!!
override fun onCreate(savedInstanceState: Bundle?) {
_binding=ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.apply{ //5.işlemimiz ;)
editText
}
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
fun aktiviteDegistir (view:View){
val kullaniciVerisi = editText.text.toString()
val intent = Intent(applicationContext,IkinciActivity::class.java)
intent.putExtra("yollananVeri",kullaniciVerisi)
startActivity(intent)//activiteyi başlatım güzel yer
}
/*Activity2*/
val intent = intent//intent
val alinanVeri = intent.getStringExtra("yollananVeri")
textView2.text = alinanVeri
class MainActivity : AppCompatActivity() {
private var _binding: ActivityMainBinding?=null//3.islemimiz
private val binding
get()=_binding!!
override fun onCreate(savedInstanceState: Bundle?) {//4.işlemiiz
_binding=ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.apply{ //5.işlemimiz ;)
editText
}
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
After adding this code, I waited for the messages to go away, but they didn't.
my application will write something about this to the editText button will be pressed then it needs to come to the textview part in the other activity
you are following approach, that is used to bind in fragment binding. The problem is that you are setting the binding data but not connecting it with the content view. for better approach in activity view binding just the same for more cleaner activity binding.
class MainActivity : AppCompatActivity() {
private lateinit var binder : ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binder = ActivityMainBinding.inflate(layoutInflater)
setContentView(binder.root)
viewImpl()
}
/**you view calls...
* like button.setonclick() and all UI related interactions...
*/
private fun viewImpl() {
binder.run {
//here...
}
}
}
In here I have created binding lateinit var for activity binder which will be initialise when binder = ActivityMainBinding.inflate(layoutInflater) and then using that binder reference for setting my content view as setContentView(binder.root).
Happy Coding ✌️.
I have base activity< T : ViewDataBinding , VM : ViewModel > extends AppCompatActivity()
and i initialize view binding and view model but when run the app i get this error "lateinit property dataBinding has not been initialized"
I don't know what I miss or what the wrong
Below is Base Activity Code
open abstract class BaseActivity<T : ViewDataBinding , VM : ViewModel> : AppCompatActivity() {
lateinit var dataBinding : T
lateinit var viewModel : VM
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
dataBinding = getViewBinding()
setContentView(dataBinding.root)
viewModel = generateViewModel()
}
abstract fun getViewBinding(): T
abstract fun generateViewModel(): VM
and this My HomeActivity
class HomeActivity : BaseActivity<ActivityHomeBinding, HomeViewModel>() {
override fun getViewBinding(): ActivityHomeBinding = ActivityHomeBinding.inflate(layoutInflater)
override fun generateViewModel(): HomeViewModel {
return ViewModelProvider(this).get(HomeViewModel::class.java)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
dataBinding.vm = viewModel
}
}
this is the error message
Because in your base class the onCreate() with 2 parameters is not going to get called during the activity's lifecycles. And in your subclass you override the onCreate() with a parameter.
Just simple change your base class to override the onCreate() with a parameter to fix the problem. And the other thing is you implement these class the java's way.
You can just make it better this way:
BaseClass
abstract class BaseActivity<T : ViewDataBinding , VM : ViewModel> : AppCompatActivity() {
protected abstract val dataBinding : T
protected abstract val viewModel : VM
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(dataBinding.root)
}
}
Subclass:
class HomeActivity : BaseActivity<ActivityHomeBinding, HomeViewModel>() {
override val viewModel get() = ViewModelProvider(this).get(HomeViewModel::class.java)
override val dataBinding get() = ActivityHomeBinding.inflate(layoutInflater)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
dataBinding.vm = viewModel
}
}
When you are calling super.onCreate(savedInstanceState) in your HomeActivity, the onCreate from android's Activity is called, but not the onCreate from BaseActivity - because it expected second param persistentState.
So you can do this options to fix the issue:
call super method with 2 params in your HomeActivity
class HomeActivity ... {
...
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
dataBinding.vm = viewModel
}
OR
use onCreate with one param in your BaseActivity
open abstract class BaseActivity<T : ViewDataBinding , VM : ViewModel> : AppCompatActivity() {
lateinit var dataBinding : T
lateinit var viewModel : VM
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
I was making a base class so that all bindings for child will be set in base
I have done till this
abstract class BaseActivity2<B : ViewBinding?, T : BaseViewModel?> : AppCompatActivity() {
private var viewBinding: B? = null
private var baseViewModel: T? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
}
but am unable to get a way to bind view in oncreat()
generally we bind layout in view binding as
binding = ActivityLoginBinding.inflate(layoutInflater)
setContentView(binding.root)
but i am looking for generalized way in base activity
You can declare a lambda property in the constructor to create the binding object
abstract class BaseActivity<B : ViewBinding>(val bindingFactory: (LayoutInflater) -> B) : AppCompatActivity() {
private lateinit var binding: B
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = bindingFactory(layoutInflater)
setContentView(binding.root)
}
}
You can also define binding as lazy property
private val binding: B by lazy { bindingFactory(layoutInflater) }
Then you need to override nothing in your activities
class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::inflate)
Other answer will also solve problem but I would like to do in a clean way.
My Base Class
abstract class BaseVMActivity<VM : ViewModel, B : ViewBinding> : BaseActivity() {
lateinit var viewModel: VM
lateinit var binding: B
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel = ViewModelProvider(this, factory).get(getViewModelClass())
binding = getViewBinding()
setContentView(binding.root)
}
private fun getViewModelClass(): Class<VM> {
val type = (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0]
return type as Class<VM>
}
abstract fun getViewBinding(): B
}
My activity:
class MainActivity : BaseVMActivity<AppViewModel, ActivityMainBinding>() {
override fun getViewBinding() = ActivityMainBinding.inflate(layoutInflater)
}
Now I can directly access viewModel or binding:
fun dummy(){
binding.bvReport.text = viewModel.getReportText()
}
It's cleaner to override binding object getter inside the child activity I think. So:
abstract class VBActivity<VB : ViewBinding> : AppCompatActivity() {
protected abstract val binding: VB
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
}
}
And lets say MainActivity will be something like:
class MainActivity : VBActivity<ActivityMainBinding>() {
override val binding get() = ActivityMainBinding.inflate(layoutInflater)
}
How to initialize VievBinding? In AppCompactActivity version 1.0.0, it became possible to pass a layout to the parent constructor so that you would not write OnCreateView.
I do so, but then I want to use VievBinding, but it doesn’t work for me. Text is not displayed. What can be done?
class MainActivity : AppCompatActivity(R.layout.activity_main) {
override fun onStart() {
super.onStart()
var binding = ActivityMainBinding.inflate(layoutInflater)
binding.hello.text = "Hello"
}
}
class MainActivity : AppCompatActivity(R.layout.activity_main) {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.bind(findViewById(Window.ID_ANDROID_CONTENT).getChildAt(0))
}
Although it's easier if you rely on __Binding.inflate().
class MainActivity : AppCompatActivity {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater, R.layout.activity_main)
setContentView(binding.root)
}
Layout inflation should not be in onStart. It goes in onCreate in Activity, and onCreateView in Fragment.
// Activity class
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState);
val binding:YourActivityLayoutBinding =
DataBindingUtil.setContentView(this, R.layout.your_activity_layout);
}
Layout views in xml should be surrounded by <layout> tag
<layout>
...// your activity view layout
</layout>
var binding = ActivityMainBinding.inflate(layoutInflater)
This will inflate the layout again and you will get a different instance of the views than what is already set in the activity
Try using the below code to bind the activity view to the binder. Where ROOT_VIEW_ID is view id of root view in your layout
var binding = ActivityMainBinding.bind(findViewById(ROOT_VIEW_ID))*
*binding.hello.text = "Hello"
i'm new on kotlin and kodein development.
I want to inject data to a simple class which extends nothing.
I have my MainActivity which extends KodeinAppCompatActivity(),
my fragment which extends KodeinSupportFragment() calls a function from my simple class CallType. But this function must to change a boolean from an other simple class ConnectivitySate. I don't want to use static value.
Below, my code :
class App : Application(), KodeinAware {
override val kodein by Kodein.lazy {
import(autoAndroidModule(this#App))
bind<CallType>() with instance(CallType())
bind<ConnectivityState>() with instance(ConnectivityState())
bind<ContactData>() with instance(ContactData())
}
override fun onCreate() {
super.onCreate()
registerActivityLifecycleCallbacks(androidActivityScope.lifecycleManager)
}
MainActivity :
class MainActivity : KodeinAppCompatActivity() {
My Fragment :
class JournalFragment : KodeinSupportFragment(){
private val callType: CallType by instance()
#SuppressLint("MissingSuperCall")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
initializeInjector()
}
override fun onCreateView(inflater: LayoutInflater?, container:
ViewGroup?,savedInstanceState: Bundle?): View? {
// !! CALL MY FUNCTION !!
callType.call(callType.callNumber)
}
....
#SuppressLint("MissingSuperCall")
override fun onDestroy() {
super.onDestroy()
destroyInjector()
}
My simple class :
class CallType {
fun call(number: String) {
// !! I want to change gsmState value from ConnectivityState class
connectivityState.gsmState = true
}
My ConnectivityState class :
class ConnectivityState {
var gsmState = false
}
It is an example among many others, because in lots of situations, i'm blocked like that. I have try lots of things but i always have like error : value not injected
Thank you very much for your reply..
When you call super.onCreate(), it calls onCreateView, so the line callType.call(callType.callNumber) is called before initializeInjector().
Note that you should always call initializeInjector() before calling super.onCreate():
override fun onCreate(savedInstanceState: Bundle?) {
initializeInjector()
super.onCreate(savedInstanceState)
}