I found in stack a lot of topic's about singleton. But in my opinion, singleton in Kotlin can be simpler:
class SingletonTwo private constructor(){
var myAge: Int = 16
companion object {
val ourInstance = SingletonTwo()
}
}
Now I can get access in other class to this variable myAge:
var abc: Int
abc = SingletonTwo.ourInstance.myAge
Something is wrong here ? This singleton is a little smaller than in other subjects on stack.
Please someone correct me if I'm wrong.
Declaring something with the object keyword instead of class makes it a singleton on its own:
object SingletonTwo {
var myAge: Int = 16
}
In this case, you can access the variable like so:
var abc: Int = SingletonTwo.myAge
You can see the docs about object declarations which also notes that they should be used to easily create singletons.
Related
I'm not very clear about the best way to inject into a static methods helper class (lets say a Custom class).
I'm kinda new to Kotlin, and as I've learnt we can access a method statically in two ways:
Object class.
Class + companion object.
To start, I'm not sure which one is the most recommended one (if there is a best practice regarding this), but my "problem" arises when needing to inject dependencies into a static method class.
Let's go with a simple example:
I have a static methods class called AWUtils (not decided if it should be an object class or a class with companion object yet though, and this will most likely depend on the injection mechanism recommended) with the next method:
fun setAmpersand2Yellow(text2Replace: String, target: String): String {
return text2Replace.replace(
target, "<span style=\"color:" +
app.drawerFooterColor + ";\">" + target + "</span>"
)
}
Here, app is the instance of my AppSettings class which holds all app configuration so, as you see setAmpersand2Yellow needs AppSettings, and of course I would't pass it as a parameter by any means, so it's a AWUtils dependence.
Using AWUtils as a class with companion object for the static methods I cannot inject directly AppSettings into company object as far as I know (at least I cannot do constructor injection, let me know if I'm wrong) and if I inject into companion object parent class (AWUtils) constructor then I don't know how to access those dependences from the companion object itself (the child).
If I use fields injection in AWUtils as a class then it complains than lateinit field has not been initialised and I don't know how to deal with this, because as far as I know lateinit fields are initialised in onCreate, which does not exist in this kind of classes.
One other possibility is to use an object with fields and set the dependencies values from caller in a static way before calling the method, for example:
object AWUtils {
var app: AppSettings? = null
fun setAmpersand2Yellow(text2Replace: String, target: String): String {
return text2Replace.replace(
target, "<span style=\"color:" +
app.drawerFooterColor + ";\">" + target + "</span>"
)
}
}
#AndroidEntryPoint
class OtherClass
#Inject constructor(private val app: AppSettings) {
fun AnyFunction() {
var mystr = "whatever"
AWUtils.app = app
var yellowStr = AWUtils.setAmpersand2Yellow(myStr)
}
}
In the end, I'm not sure on how to supply dependencies to a static methods class and which form of "static" class should I choose.
Edit 1:
Apart from my ApSettings class, I need a context, like for example in this next isTablet method:
val isTablet: String
get() {
return ((context.resources.configuration.screenLayout
and Configuration.SCREENLAYOUT_SIZE_MASK)
>= Configuration.SCREENLAYOUT_SIZE_LARGE)
}
In the end, I need a context and my AppSettings (or any other custom classes) to be injected anyway in a class with static methods.
Edit 2:
I could do (from the activity):
AWUtils.context = this
AWUtils.app = app
var isTablet = AWUtils.isTablet
And it works, but rather to be in the need of assigning a value to two fields (or more) every time I need to call a static method, I would prefer the fields to be injected in any way.
That's what dependency injection is meant for, isn't it?
Edit 3: I'm starting to be fed up with Hilt, what is supposed would have been created to simplify our life, only makes our programming life much more complicated.
As you clarified in the comments, you want to have your utils class accessible in an easy way across your codebase, so this answer will focus on that and on your original questions.
I'm kinda new to Kotlin, and as I've learnt we can access a method statically in two ways: Object class or Class + companion object.
Kotlin does not have Java-style statics. One reasoning behind it was to encourage more maintainable coding practices. Static methods and static classes are also a nightmare for testing your code.
In Kotlin you would go with an object (but a class + companion object would work in the same way)
object AWUtils {
lateinit var appContext: Context
lateinit var appSettings: AppSettings
fun initialize(
appContext: Context,
appSettings: AppSettings,
// more dependencies go here
) {
this.appContext = appContext
this.appSettings = appSettings
// and initialize them here
}
val isTablet: Boolean
get() = ((appContext.resources.configuration.screenLayout
and Configuration.SCREENLAYOUT_SIZE_MASK)
>= Configuration.SCREENLAYOUT_SIZE_LARGE)
fun setAmpersand2Yellow(text2Replace: String, target: String): String {
return text2Replace.replace(
target, "<span style=\"color:" +
appSettings.drawerFooterColor + ";\">" + target + "</span>"
)
}
}
Since this object should be accessible across the whole application it should be initialized as soon as possible, so in Application.onCreate
#HiltAndroidApp
class Application : android.app.Application() {
// you can inject other application-wide dependencies here
// #Inject
// lateinit var someOtherDependency: SomeOtherDependency
override fun onCreate() {
super.onCreate()
// initialize the utils singleton object with dependencies
AWUtils.initialize(applicationContext, AppSettings())
}
Now anywhere in your app code you can use AWUtils and AppSettings
class OtherClass { // no need to inject AppSettings anymore
fun anyFunction() {
val mystr = "whatever"
val yellowStr = AWUtils.setAmpersand2Yellow(myStr)
// This also works
if (AWUtils.isTablet) {
// and this as well
val color = AWUtils.appSettings.drawerFooterColor
}
}
}
There is another way in Kotlin to write helper/util functions, called extension functions.
Your isTablet check might be written as an extension function like this
// This isTablet() can be called on any Configuration instance
// The this. part can also be omitted
fun Configuration.isTablet() = ((this.screenLayout
and Configuration.SCREENLAYOUT_SIZE_MASK)
>= Configuration.SCREENLAYOUT_SIZE_LARGE)
// This isTablet() can be called on any Resources instance
fun Resources.isTablet() = configuration.isTablet()
// This isTablet() can be called on any Context instance
fun Context.isTablet() = resources.isTablet()
With the above extension functions in place the implementation inside AWUtils would be simplified to
val isTablet: Boolean
get() = appContext.isTablet()
Inside (or on a reference of) any class that implements Context, such as Application, Activity, Service etc., you can then simply call isTablet()
class SomeActivity : Activity() {
fun someFunction() {
if (isTablet()) {
// ...
}
}
}
And elsewhere where Context or Resources are available in some way, you can simply call resources.isTablet()
class SomeFragment : Fragment() {
fun someFunction() {
if (resources.isTablet()) {
// ...
}
}
}
Edit 3: I'm starting to be fed up with Hilt, what is supposed would have been created to simplify our life, only makes our programming life much more complicated.
Yeah, Hilt is focusing on constructor injection and can only do field injection out-of-the-box in very limited cases, afaik only inside Android classes annotated with #AndroidEntryPoint and inside the class extending the Application class when annotated with #HiltAndroidApp.
Docs for #AndroidEntryPoint say
Marks an Android component class to be setup for injection with the standard Hilt Dagger Android components. Currently, this supports activities, fragments, views, services, and broadcast receivers.
If you feel that you need a lot of field injection, because you are working with "static"-like objects in Kotlin, consider using Koin instead of Hilt for your next project.
I need to inherit the Object A from Object B, were both the objects consist of constants only.
Example
Object A {
const val a1 = "some_data_1"
const val a2 = "some_data_2"
}
Object B : A {
const val b1 = "some_data_3"
}
is it feasible to achieve this in kotlin ?
Kotlin is an object-oriented programming (OOP) language. We can inherit object A from object B for that we have to to allow class "A" to be inherited, for that we need to attach the open modifier before the class to make it non-final.
For the const we have to use companion object, which is an object that is common to all instances of that class.
open class A {
companion object {
const val a1 = "some_data_1"
const val a2 = "some_data_2"
}
}
class B : A() {
companion object {
const val b1 = "some_data_3"
}
val a_1 = a1
val a_2 = a2
}
Check this link to understand inheritance
Check this link to understand Companion Object
open class A {
companion object {
const val a1 = "some_data_1"
const val a2 = "some_data_2"
}
}
class B : A() {
companion object {
const val b1 = "some_data_3"
}
val a_1 = a1
val a_2 = a2
}
for a class to be inherited in Kotlin it should be open for example open class A {}
for class B to extends class A should add the class B : A()
for constants should be inside a companion object {}
I would probably dive a bit deeper.
Object in your example is an Object Declaration.
You should have a look at this doc describing Object Declarations and Object Expressions.
The question is - Why would you need to have one class only with constants extend another(also containing only const vals)?
Object Declarations are Kotlin built in Singletons and BTW are thread safe.
Example :
object DeviceProvider {
private val _devices = ArrayList<Device>()
fun getDevices() = _devices as List<Device>
fun registerDevice(device: Device) {
_devices.find { it == device } ?: _devices.add(device)
}
}
Usage :
fun addDevice(){
ServiceProvider.registerDevice(Device("1234"))
}
Object declarations are allowed to extend open classes and interfaces - so you can define a behavior or even a state via inheritance. As usual you can have a look at Kotlin docs about inheritance, those are exhaustive and nice read.
Still if we are talking about common approaches defining const values - then separate file is the best solution, if of course that value should be bound to any specific class. Here is a nice point of view(thanks Marko for your answer) :
In Java you're forced to put all static field and method declarations
in a class and often you even have to create a class just for that
purpose. Coming to Kotlin, many users look for the equivalent facility
out of habit and end up overusing companion objects.
Kotlin completely decouples the notions of a file and a class. You can
declare any number of public classes is the same file. You can also
declare private top-level functions and variables and they'll be
accessible only to the classes within the same file. This is a great
way to organize closely associated code and data.
While learning ViewModels in Android, a problem has arisen that feels like Kotlin was meant to solve. In the code below, we can see that MutableLiveData values are being use to edit values and indicators. However, we do not want these mutable values to be exposed to anything else, specifically members of an Android lifecycle. We DO want Android Lifecycle members to have access to read values but not set them. Therefore, the 3 exposed functions, displayed below, are of the LiveData<> immutable type.
Is there an easier or more concise way to expose read only values that can be edited internally? This seems like what Kotlin was made to avoid: boilerplate verbosity.
class HomeListViewModel: ViewModel(){
//Private mutable data
private val repositories = MutableLiveData<List<Repo>>()
private val repoLoadError = MutableLiveData<Boolean>()
private val loading = MutableLiveData<Boolean>()
//Exposed uneditable LIveData
fun getRepositories():LiveData<List<Repo>> = repositories
fun getLoadError(): LiveData<Boolean> = repoLoadError
fun getLoadingStatuses(): LiveData<Boolean> = loading
init{...//Do some stuff to MutableLiveData<>
}
}
A non-Android scenario that might be similar is:
class ImmutableAccessExample{
private val theThingToBeEditedInternally = mutableListOf<String>()
fun theThingToBeAccessedPublicly(): List<String> = theThingToBeEditedInternally
init {
theThingToBeEditedInternally.add(0, "something")
}
}
I don't know if it is possible to avoid the verbosity. But, I've seen that before and it is usually declared as a property.
private val _repositories = MutableLiveData<List<Repo>>()
val repositories : LiveData<List<Repo>>
get() = _repositories
This is the convention, see the doc here in Names for backing properties
If a class has two properties which are conceptually the same but one is part of a public API and another is an implementation detail, use an underscore as the prefix for the name of the private property:
Following the idea of this post:
class HomeListViewModel: ViewModel(){
val repositories: LiveData<List<Repo>> = MutableLiveData()
init {
repositories as MutableLiveData
...//Do some stuff to repositories
}
}
I haven't found any elegant solution to this problem however this is how I handle it.
private val selectedPositionLiveData = MutableLiveData<Int>()
fun getSelectedPosition() = selectedPositionLiveData as LiveData<Int>
The View observes via the public getter method and there's no need to define a second member in the ViewModel. I probably favour this approach due to my Java background with explicit getters but this seems to me to be as clean and concise as any of the other workarounds.
val doesn't have a setter since it's readonly but if you want a var you can do this
var repositories = MutableLiveData<List<String>>()
private set
var repoLoadError = MutableLiveData<Boolean>()
private set
var loading = MutableLiveData<Boolean>()
private set
This will give you a private setter and a public getter
In Java and Android, we can do this:
public static MyApplication extends Application {
private static Context appContext;
public void onCreate() {
appContext = this;
}
public static Context getAppContext() {
return appContext;
}
}
so that, somewhere else, we can do this:
appContext = MyApplication.getAppContext();
How do we do this in Kotlin? I've been going round in circles for the past hour or so.
Thanks in advance.
//Edit
Perhaps I should have been clearer. I meant how can we write the above in Kotlin and use it in Kotlin.
In Kotlin this is called the 'companion object':
class MyApplication: Application {
companion object {
var appContext: Context? = null
private set
}
}
The key element I was missing was the use of an init block to set the appContext that is inside the companion object (I had already tried the companion object path but was struggling to actually get appContext set).
See code below:
class MyApplication : Application() {
init {
appContext = this
}
companion object {
lateinit var appContext: Context
private set
}
}
This is then callable as usual via:
val testContext = MyApplication.appContext
Assumed you have some java code in android and you want to convert it to kotlin code:
Visit Link
find Convert from java
it's help me to convert java code I've found on internet and converting it to kotlin code,
may this answer not help you about your question, but it would help you to convert what you know in java that you don't know how-to-do in kotlin
you can use it this way
companion object{
//your static fields
}
to call it from kotlin ==> ClassName.FieldName
to call it from java ==> ClassName.Companion.getFieldName()
It seems like you want only one object of this class at runtime. This is called a singleton. There are recommendations to implement that properly in Java. Luckily Kotlin directly allows you to declare singleton objects on the top scope:
val o = object { your attributes and methods here}
I develop Android applications and often use annotations as compile time parameter checks, mostly android's support annotations.
Example in java code:
public class Test
{
#IntDef({Speed.SLOW,Speed.NORMAL,Speed.FAST})
public #interface Speed
{
public static final int SLOW = 0;
public static final int NORMAL = 1;
public static final int FAST = 2;
}
#Speed
private int speed;
public void setSpeed(#Speed int speed)
{
this.speed = speed;
}
}
I don't want to use enums because of their performance issues in Android. The automatic converter to kotlin just generates invalid code. How do I use the #IntDef annotation in kotlin?
Edit: In case you miss the comments on the question or this answer, it's worth noting that the following technique compiles,
but does not create the compile-time validation you would get in
Java (which partially defeats the purpose of doing this). Consider using an enum
class
instead.
It is actually possible to use the #IntDef support annotation by defining your values outside of the annotation class as const vals.
Using your example:
import android.support.annotation.IntDef
public class Test {
companion object {
#IntDef(SLOW, NORMAL, FAST)
#Retention(AnnotationRetention.SOURCE)
annotation class Speed
const val SLOW = 0L
const val NORMAL = 1L
const val FAST = 2L
}
#Speed
private lateinit var speed: Long
public fun setSpeed(#Speed speed: Long) {
this.speed = speed
}
}
Note that at this point the compiler seems to require the Long type for the #IntDef annotation instead of actual Ints.
There's currently no way to achieve exactly this in Kotlin, since an annotation class cannot have a body and thus you cannot declare a constant in it which would be processed by IntDef. I've created an issue in the tracker: https://youtrack.jetbrains.com/issue/KT-11392
For your problem though, I recommend you use a simple enum.
Update:
Forget #IntDef and #StringDef, Now, with ART, you can use enums instead.
From the official GoogleIO:
https://www.youtube.com/watch?v=IrMw7MEgADk&feature=youtu.be&t=857
Plus, if you're still not sure if you should use enums, you can hear a bunch of people yelling at each other in the comments of the first answer over here:
https://stackoverflow.com/a/37839539/4036390
Old answer:
Just create the #IntDef class as a java class and access it via kotlin code.
Example:
Create your type class:
public class mType {
#IntDef({typeImpl.type1, typeImpl.type2, typeImpl.type3})
#Retention(RetentionPolicy.SOURCE)
public #interface typeImpl {
int type1 = 0;
int type2 = 1;
int type3 = 2;
}
}
Put this function in any Kotlin object:
object MyObject{
fun accessType(#mType.typeImpl mType: Int) {
...
}
}
then access it:
fun somOtherFunc(){
MyObject.accessType(type1)
}
**Notice: you don't have to put the access method inside an object.
Use this:
companion object {
const val FLAG_PAGE_PROCESS = 0L//待处理
const val FLAG_PAGE_EXCEPTION = 1L//设备异常
const val FLAG_PAGE_UNCHECKED = 2L//未审核
const val FLAG_PAGE_AUDIT = 3L//统计
val FLAG_PAGE = "FLAG_PAGE"
fun newInstance(#FlagPageDef flagPage: Int): RepairFormsListFragment {
val fragment = RepairFormsListFragment()
val args = Bundle()
fragment.arguments = args
return fragment
}
#Retention(AnnotationRetention.SOURCE)
#IntDef(FLAG_PAGE_PROCESS, FLAG_PAGE_EXCEPTION, FLAG_PAGE_UNCHECKED, FLAG_PAGE_AUDIT)
annotation class FlagPageDef
}