I need to create a private field and use it without access to it from other classes. But i can't instantiate it in a constructor.
I'm developing for Android, and a problematic field screenWakeLocker can`t be instantiated this way:
class MainActivity : AppCompatActivity() {
private val screenWakeLocker: PowerManager.WakeLock =
(getSystemService(Context.POWER_SERVICE) as PowerManager)
.newWakeLock(PowerManager.FULL_WAKE_LOCK, "")
"System services not available to Activities before onCreate()"
So i instantiate it in OnCreate:
class MainActivity : AppCompatActivity() {
private var game: Game = Game()
private var screenWakeLocker?: PowerManager.WakeLock;
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
screenWakeLocker = (getSystemService(Context.POWER_SERVICE) as PowerManager).newWakeLock(PowerManager.FULL_WAKE_LOCK, "")
}
override fun onResume(){
super.onResume()
screenWakeLocker.acquire()
}
and get a compilation error "Property getter or setter expected" at ?: PowerManager.WakeLock
How to make it unavailable to other classes and to use it?
You have two options:
option one, if you want to use "var" you can add lateinit
option two, you can use by lazy, where objects are initialised when it is needed
private lateinit var screenWakeLocker: PowerManager.WakeLock
private val screenWakeLockerTwo by lazy {(getSystemService(Context.POWER_SERVICE) as PowerManager).newWakeLock(PowerManager.FULL_WAKE_LOCK, "")}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
screenWakeLocker = (getSystemService(Context.POWER_SERVICE) as PowerManager).newWakeLock(PowerManager.FULL_WAKE_LOCK, "")
}`
I think option two is better.
Use lateinit keyword for lazy initialization.
private lateinit var screenWakeLocker: PowerManager.WakeLock
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 an activity that has a button. On the button click I want to update text in text view.
I want to use ViewBinding instead of the normal findViewById
This is how I created the val binding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = ActivityMainBinding.inflate(layoutInflater);
setContentView(binding.root)
binding.btnRoll.setOnClickListener {
rollDice()
}
}
Now in rollDice I want to update the text view but I'm not able to access binding which make sense because its scope is limited to onCreate() , so what is the best practice for this?
private fun rollDice() {
val random = Random().nextInt(6) + 1
binding.txt_random.setText("random")
}
You have two options.
1. Store in a property
Since the inflated content of Activity is fully bound to it's lifecycle, it's safe to keep the reference as a property
class MainActivity : AppCompatActivity() {
lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater);
setContentView(binding.root)
binding.btnRoll.setOnClickListener {
rollDice()
}
}
private fun rollDice() {
val random = Random().nextInt(6) + 1
binding.txt_random.setText("random")
}
}
2. Pass the binding to the methods
That's what I usually do, it avoids creating a property where it's not really a necessity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = ActivityMainBinding.inflate(layoutInflater);
setContentView(binding.root)
binding.btnRoll.setOnClickListener {
rollDice(binding)
}
}
private fun rollDice(binding: ActivityMainBinding) {
val random = Random().nextInt(6) + 1
binding.txt_random.setText("random")
}
}
Both options are valid ways to make the binding visible to Activities methods.
Store the binding in an instance variable on the Activity. Then you have access to it from all the methods in the Activity.
As the question has accepted answer and it is already addressed but here is my approach to the viewBinding
class MainActivity : AppCompatActivity() {
private val binding by lazy{
ActivityMainBinding.inflate(layoutInflater)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
binding.btnRoll.setOnClickListener {
rollDice()
}
}
private fun rollDice() {
val random = Random().nextInt(6) + 1
binding.txt_random.setText("random")
}
}
I go with lazy initialization of binding so that way it is only intitialized if it is required.
More you can read about lazy initialization here
https://www.baeldung.com/kotlin/lazy-initialization
what to do so?
I declared the val here, so that i can use the val e11 in all the function but it get crashes and why?
//val e11=findViewById<EditText>(R.id.e1)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_lifecycle)
val b11=findViewById<Button>(R.id.b1)
b11.setOnClickListener{
startActivity(Intent(this,another::class.java))
}}
override fun onStart() {
super.onStart()
Toast.makeText(this, "am started", Toast.LENGTH_SHORT).show()
}override fun onResume() {
super.onResume()
Toast.makeText(this, "am resumed", Toast.LENGTH_SHORT).show()
}
override fun onPause() {
super.onPause()
val e1=findViewById<EditText>(R.id.e1)
e1.setText("")
}
}```
Try this
private val e11 : EditText by lazy { findViewById<EditText>(R.id.e1) }
As #Kishan Maurya stated out in the comments, you are trying to find a view before the view gets created in your onCreate function. A solution could be to declare e11 globally and initiate it in your onCreate like it is most common. Or you try out #Kishan Maurya's answer.
lateinit var e11 : EditText // declare var e11 globally
// lateint is a keyword to tell that this var will be initialized later
// you need a var instead of val, because e11 should not be final
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
e11 = findViewById<EditText>(R.id.e11)
// you could also initialize like below; is simple and has better readability
// e11 = findViewById(R.id.e11) as EditText
}
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)
}
I am new in Android development and I provided my code snippet.
I'm wondering why is it saying other must not be null
other = findViewById(R.id.otherId)
My Activity:
class SplashScreen : AppCompatActivity() {
lateinit var topAnimation:Animation
lateinit var bottomAnimation:Animation
lateinit var logoImage:ImageView
lateinit var bangerText:TextView
override fun onCreate(savedInstanceState: Bundle?) {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_splash_screen)
topAnimation=AnimationUtils.loadAnimation(this,R.anim.top_animation)
bottomAnimation=AnimationUtils.loadAnimation(this,R.anim.bottom_animation)
logoImage=findViewById(R.id.logoImage)
bangerText=findViewById(R.id.bangerTextView)
val other=findViewById<TextView>(R.id.textView5)
logoImage.animation=topAnimation
bangerText.animation=bottomAnimation
other.animation=bottomAnimation
}
}
Can you check whether layout/activity_splash_screen.xml actually has id/textView5?
If that id is not specified in that layout, findViewById might return null