Kotlin: Overload resolution ambiguity - java

Trying to execute the below code :
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Test().list.contains(1)
}
}
public class Test {
ArrayList<Integer> list;
public ArrayList<Integer> getList() {
return list;
}
}
and compilation fails at Test().list.contains(1) with message :
Task :app:compileDebugKotlin FAILED
e: /Users/sreejithcr/Documents/MyApplication/app/src/main/java/com/wxample/myapplication/MainActivity.kt: (13, 31): Overload resolution ambiguity:
public open fun contains(#Nullable element: Int!): Boolean defined in java.util.ArrayList
public open fun contains(#Nullable element: Int!): Boolean defined in java.util.ArrayList
What i understand is compiler finds 2 contains() with exact same signature and not sure which one to call.
gradle config :
ext.kotlin_version = '1.3.41'
classpath 'com.android.tools.build:gradle:3.4.2'

It is an issue with Android Studios API 29 R2
https://issuetracker.google.com/issues/139041608#comment3
Go Tools -> SDK Manager -> Uninstall Android 9.+, then install it again as Google rolled back R2 so you'll be back to R1

As I read through your code I noticed some conflicts:
First, Test needs a public constructor, which creates the ArrayList, sth. like:
public Test(){
list = new ArrayList<>();
}
Second, make the variable list private, access should only be granted through getter/setter.
Third, in method onCreate() try:
new Test().getList().contains(1);

Related

How to pass callback function from Java to Kotlin class

I have a Kotlin class as follows (this is a sample for ease, hence it doesn't 'do' anything useful)
class MyKotlinClass (private val handleSomeCallBack: (ByteArray) -> Unit) {
private val someBuffer = BytesBuilder()
fun myFunction(bytesList: List<Byte>) {
handleSomeCallBack(someBuffer.toArray())
}
}
I want to call this code from a java class, hence, in that class I have the following declared:
public MyJavaClass() {
messageParser = new MyClass(handleSomeCallback);
}
The callback method being passed is:
private void handleSomeCallback(byte[] dataBytes) {
}
(MyClass is correctly declared within the file)
The issue I'm having is that I can't figure out how to pass the callback to the constructor of MyKotlinClass.
I have tried a variety of things including
messageParser = new MyClass(handleSomeCallback(byte[] dataBytes));
messageParser = new MyClass(this::handleSomeCallback(byte[] dataBytes));
But no matter what I try I receive an error.
I believe the answer is to do with lambdas but I can't quite see what the syntax should be for calling this from Java.
You can go with something like this:
MyKotlinClass instance = new MyKotlinClass(byteArray -> {
// your code
return Unit.INSTANCE;
});
Or use Unit as return type of your separate method like suggested by #ADM here
You just need to add
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
to your android block in app build.gradle

How to call Kotlin class from Java class

I need to pass intent from java activity to Kotlin activity:
Java activity ProfileActivity.class:
Intent selectGameIntent = new Intent(ProfileActivity.this, kotlin.jvm.JvmClassMappingKt.getKotlinClass(CreateNewPollUserActivity.class).getClass());
startActivity(selectGameIntent);
And this is my Kotlin activity:
class CreateNewPollUserActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_create_new_poll_user)
val max = 45
val min = 10
val total = max - min}}
When i run it i have an error:
cannot find symbol
import com.myvote.Profile.ToolbarOption.CreateNewPollUserActivity;
any ideas how send intent from java activity to Kotlin activity?
add this in build.gradle project
buildscript {
ext.kotlin_version = '1.5.21'
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
And on top of build.gradle module file
apply plugin: 'kotlin-android'
This is the way to use call Kotlin class from Java class
Intent selectGameIntent = new Intent(ProfileActivity.this,
CreateNewPollUserActivity.class);
startActivity(selectGameIntent);
In your code, Probably the problem lays not in the Java-Kotlin relation, but in something else. Please check your code/project.
For this aim, you need to do several steps:
1-build.gradle project
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.10'
2- build.gradle app
plugins {
id 'com.android.application'
id 'kotlin-android'
}
3- Introduction the class and fun:
kotlin kt:
class CountTime(val activity: Activity) {
fun seeNext(t: String, c: String, ico: Int, i: Int) {
java MainActivity
CountTime countTime = new CountTime(this);
countTime.seeNext(t,c,ico,i);
and if there is a companion object
.Companion.getInstance();

Dagger 2 Good practices to build components in Application class

I know probably there is no clear answer for this question.
But I would like to know Your opinions and maybe new ideas.
I'm wondering which of the following options is the best/right/correct way to build the app-level Dagger Component in Application class.
Example 1:
public class MyApp extends Application {
private NetComponent mNetComponent;
#Override
public void onCreate() {
super.onCreate();
mNetComponent = DaggerNetComponent.builder()
.appModule(new AppModule(this))
.netModule(new NetModule("https://api.github.com"))
.build();
}
public NetComponent getNetComponent() {
return mNetComponent;
}
}
Usage:
((MyApp) getApplication()).getNetComponent().inject(this);
Example 2:
class MyApplication extends Application {
private static MyComponent component;
#Override
void onCreate() {
component = DaggerMyComponent.builder()
.contextModule(new ContextModule(getApplicationContext()))
.build();
}
public static MyComponent getMyComponent() {
return component;
}
}
Usage:
MyApplication.getMyComponent().inject(this)
Example 3:
class CustomApplication: Application() {
lateinit var component: SingletonComponent
private set
override fun onCreate() {
super.onCreate()
INSTANCE = this
component = DaggerSingletonComponent.builder()
.contextModule(ContextModule(this))
.build()
}
companion object {
private var INSTANCE: CustomApplication? = null
#JvmStatic
fun get(): CustomApplication = INSTANCE!!
}
}
Then:
class Injector private constructor() {
companion object {
#JvmStatic
fun get() : SingletonComponent = CustomApplication.get().component
}
}
Usage:
Injector.get().catRepository()
Example 4:
class App : Application() {
var repositoryComponent: RepositoryComponent? = null
var appComponent: AppComponent? = null
override fun onCreate() {
super.onCreate()
instance = this
appComponent = DaggerAppComponent.builder().application(this).build()
repositoryComponent = DaggerRepositoryComponent.builder().build()
}
companion object {
private var instance: App? = null
fun get(): App {
return instance!!
}
}
}
Usage:
App.get().repositoryComponent!!.inject(this)
What do you think about this? Is there any better / cleaner way to do this? Maybe provided examples are fine? Or maybe just one of them?
I will be grateful for any good examples / tips / advices.
Thanks!
Okay, no one answered in 5 days so it's my turn, despite my bias :p
Option #1
((MyApp) getApplication()).getNetComponent().inject(this);
It's an "ok" version of doing things, except for two things.
First, the name. NetComponent isn't really for networking, it's the app-global singleton component, so it should be either called SingletonComponent or AppComponent. But naming it NetComponent is disingenuous, it's typically responsible for everything else too.
Second problem is that you need a reference to Context to access your dependency graph, making Context actually be a dependency rather than it being provided to you.
Option #2
MyApplication.getMyComponent().inject(this)
This is a perfectly fine way of doing things, but you need to know that to reach your object graph, you need to access the static method of MyApplication.
Option #3
Injector.get().inject(this)
Internally, this solution actually just calls over to get the app component, public static AppComponent get() { return MyApplication.getInstance().getComponent(); }
The benefit is that getComponent() is exposed via an instance method of Application, so it could be theoretically swapped out.
Also, invoking a method on something called Injector.get() is more obviously an "injector" than, well, an application class.
As for whether you use .catRepository() or .inject(this), it's up to you; but I personally prefer calling the provision methods to get the deps in Activity/Fragment, because listing the member-injection targets adds a lot of clutter to the component over time.
4.)
App.get().repositoryComponent!!.inject(this)
You can ditch the !! if repositoryComponent is a lateinit var.
Having two components for the same scope (and therefore two different object graphs) will only cause trouble, out of all of the options, this is the worst.
In my opinion, the 3rd option is the best. Technically it's the same as option #2 with an additional "indirection" through the instance method of Application that actually returns the component.

Passing parameters at runtime dagger 2

I have a module, UserModule that takes in a string and provides a user object.
UserModule:
#Module
class UserModule(val name: String) {
#Provides
fun provideUser() : User = User(name = name)
}
And a ViewModelComponent that has UserModule as one of its components
ViewModelComponent:
#Singleton
#Component(modules = [UserModule::class])
interface ViewModelComponent {
fun inject(activity: MainActivity)
}
Normally I would provide the component in my application like this:
class MainApplication : Application() {
lateinit var component: AppComponent
override fun onCreate() {
super.onCreate()
component = DaggerAppComponent.builder()
.userModule(UserModule("Name"))
.build()
}
}
And reference it in my activity like this:
class MainActivity : AppCompatActivity() {
#Inject lateinit var user: User
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
(application as MainApplication).component.inject(this)
}
However, this assumes that the value of UserModule name is known at runtime and is hardcoded into MainApplication, however, in reality, the value of name is obtained from MainActivity.
The only solution I can think of is to build the dependency graph in MainActivity so I am able to pass name like this:
class MainActivity : AppCompatActivity() {
#Inject lateinit var user: User
val newUserName = "NewName"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
component = DaggerAppComponent.builder()
.userModule(UserModule(newUserName))
.build()
component.inject(this)
}
This solution seems very unefficient but it is the only way I can inject dynamic parameters in Dagger 2. Is there a better way to achieve this
I just ran into this issue aswell, first solution that I thought of was to create some "static holder" class that would hold dynamic parameters and it would be developers responsibility to update this holder at the right time - before injection happens I guess. I didnt actually try it though and it doesnt seem to be too clean either.
Anway after a bit of googling I found this article: https://proandroiddev.com/dagger-2-module-parameters-7c820d944a which seems to be more "dagger oriented" solution, didnt try that either, but it's something you can start with.
I would only comment this but I dont have required reputation...

Reverting Kotlin to Java codes in Android Studio Canary 5

I'm making an Android app coding in Java just like everybody else's do. Since Android Studio 3.o Canary was released and adding support for Kotlin, I took a chance to give a try. Downloaded the plugins and setup the Gradle file correctly.
But once the activity is converted into Kotlin and synced, an error occured.
Below is my build.gradle,
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
and,
ext.kotlin_version = '1.1.3'
Dependencies, [
So, Im thinking to go back to Java until the issue is solved.
The Kotlin code are,
class Welcome : AppCompatActivity() {
internal var rujuk = FirebaseDatabase.getInstance().reference /*3rd step, DB reference*/
/*4th, initially write under onStart method, then CnP here, value inside child() should be same as in DB.*/
internal var referKpdTeksView = rujuk.child("intro")
#BindView(R.id.buku) internal var buku: ImageView? = null
#BindView(R.id.wel) internal var teksTajuk: TextView? = null /*1st step, declare variable for each Text*/
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_welcome)
ButterKnife.bind(this)
rujuk.keepSynced(true)
Glide.with(this).load("https://firebasestorage.googleapis.com/v0/b/travel-and-go-93552.appspot.com/o/buku.png?alt=media&token=bad59236-e4ff-44e0-81ac-32adf9c1aea4").diskCacheStrategy(DiskCacheStrategy.SOURCE).into(buku!!)
}
#OnClick(R.id.enterButton)
fun g() {
val EnterButton = Intent(this#Welcome, CountryList::class.java)
startActivity(EnterButton)
}
/*5th step, create onStart method*/
override fun onStart() {
super.onStart()
/*DB reference 4th step
* Syntax;
* DatabaseReference.addValueEventListener(new ValueEventListener)*/
referKpdTeksView.addValueEventListener(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
val ayat = dataSnapshot.getValue(String::class.java)
teksTajuk!!.text = ayat
}
override fun onCancelled(databaseError: DatabaseError) {
}
})
}
}
and the error is,
Error:Failed to delete original file 'C:\Users\MohdA\AppData\Local\Temp\gradle_download1285409691272083864bin' after copy to 'C:\Users\MohdA.gradle\caches\modules-2\files-2.1\com.android.databinding\compilerCommon\2.3.3\1f0e06d55f3f72f3192b6e026d9a5a557d9e2ea6\compilerCommon-2.3.3.jar'
In intellij i resolved by going through show history , project right click local history then show history

Categories