Android Studio IDE Code Completion Suggestions - android-studio

I'm trying to expose some APIs for developers via an interface. However, due to modularity in functions, I've broken a list of functions into several interfaces. Instead of doing:
interface IAllFeatures {
fun A() {}
fun AA() {}
fun B() {}
fun BB() {}
fun C() {}
fun CC() {}
}
interface SampleInterface : IAllFeatures {
}
I have it separated as:
interface IA {
fun A() {}
fun AA() {}
}
interface IB {
fun B() {}
fun BB() {}
}
interface IC {
fun C() {}
fun CC() {}
}
interface SampleInterface : IA, IB, IC {
}
In the first implementation, IAllFeatures displays all the functions in bold text in the code completion popup. However, in the second implementation, SampleInterface displays all functions in non-bold text and is no longer given priority in the list of code completion suggestions. Is there a way to have the best of both worlds, separating interface categories while giving developers clear code completion suggestions?

The whole point of the bold text is to show which methods are overriden/declared newly. If they are not overriden but inherited, they will not be bold. Unfortunately, the fix is, essentially, to use the first solution. You could override each method to call the super if you want, but that's pretty hacky.

Related

Android studio Kotlin OnClickListerner function

When I implemented the member in the class for the on click listener as shown below:
class QuizQuestionsActivity : AppCompatActivity(), View.OnClickListener {
I was given the option of implementing it as:
override fun onClick(p0: View?) {
I need it to be
override fun onClick(v: View?) {
can someone explain the difference and why I am not getting the option of v: View
Kotlin provide default parameter with alphabets and digits you can simply change it with your variable name like --
override fun onClick(v: View?) { }
override fun onClick(view: View?) { }
override fun onClick(myView: View?) { }
It's quit good and it's meaningful variable name that remember as long time. where P0 and P1 named variable is not like good to remember.
Hope You can understand what I mean to say.
Both of those functions are the same, it's just a different name for the View variable. Kotlin parameters are listed with the parameter name first, then the class name.
If you want p0 to be v instead, just change the parameter name to be v.

Specify an argument should implement more than one trait

To illustrate my question, better as an example: Lets say I want to host a triathlon, whereby triathletes have to Swim, Run, Cycle, so I have 3 traits:
trait Swimmer {
abstract void swim()
}
trait Runner {
abstract void run()
}
trait Cyclist {
abstract void cycle()
}
All these traits together make up a Triathlete:
trait Triathlete extends Swimmer, Runner, Cyclist {
}
Which can then do a triathlon:
def triathlon(Triathlete triathlete) {
triathlete.run()
triathlete.cycle()
triathlete.swim()
}
Currently I am defining a DSL in groovy, and in this use case, it doesn't really make sense to define this intermediate trait Triathlete. So is there a way to declare triathlon, using Swimmer & Runner & Cyclist?
I don't know if there is anything in the language itself to do this, I imagine there is a way to do this with AstBuilder or the likes but I am not there yet with my level of groovy to implement something like this, but I am looking for something like this
void triathlon(Swimmer & Runner & Cyclist triathlete) {
triathlete.run()
triathlete.cycle()
triathlete.swim()
}
Ok I figured this out, just putting this for others to use, you can use generics here, pure Java no Groovy needed:
static <T extends Swimmer & Runner & Cyclist> void triathlon(T triathlete) {
triathlete.run()
triathlete.cycle()
triathlete.swim()
}

How to make a local extension method avaiable in a function with receiver?

I found an interesting thing, but I couldn't do it. Is there any way to make the local extension method available in a function with receiver.
val list = ArrayList<Any>();
fun <T> Array<T>.bind(context: MutableList<in T>, block: Array<T>.() -> Unit) {
fun Array<T>.save() {
context.addAll(this);
}
block();
}
arrayOf(1, 2, 3).bind(list) {
save(); //todo: how to bind extension in execution scope
};
I know there is an alternative way by introducing another type for the receiver, but I want to avoid it. for example:
interface Savable {
fun save();
}
fun <T> Array<T>.bind(context: MutableList<in T>, block: Savable.() -> Unit) {
val proxy = object : Savable {
override fun save() {
context += this#bind;
}
};
proxy.block();
}
There is no such feature yet, and I think in near future it won't be added either. You should just use your second version. Don't care about adding an wrapper class. The idea of avoiding introducing a wrapper class is actually, as long as you are using JVM backend, just nonsense, because by using local function you are actually adding a local class.
This is the equivalent Java code of your kotlin function, after fixing as you have suggested, with the assumption that your bind function lives in file bind.kt:
public final class BindKt {
public static <T> void bind(T[] receiver, List<? super T> context, Function1<T> block) {
class Local { // the name of local class is unimportant, as it's generated by compiler. It should looks like "package.name.BindKt$bind$X" where X is a number.
public void save(T[] receiver) {
context.addAll(receiver);
}
}
block.invoke(this); // this won't compile. Neither will yours.
}
}
As you can see save is NOT compiled to a static method, which means, if your block somehow ever called that save, an instance of Local must be fist created. So, no matter what you do, as long as you used a local function, there is basically no point in avoiding introduing a wrapper class. Your second solution is good, and just use it. It's both elegant and efficient enough.
If you really don't want add a class/object creation, move these extension functions to a package scope, and let clients import them.

In Kotlin, how do I add extension methods to another class, but only visible in a certain context?

In Kotlin, I want to add extension methods to a class, for example to class Entity. But I only want to see these extensions when Entity is within a transaction, otherwise hidden. For example, if I define these classes and extensions:
interface Entity {}
fun Entity.save() {}
fun Entity.delete() {}
class Transaction {
fun start() {}
fun commit() {}
fun rollback() {}
}
I now can accidentally call save() and delete() at any time, but I only want them available after the start() of a transaction and no longer after commit() or rollback()? Currently I can do this, which is wrong:
someEntity.save() // DO NOT WANT TO ALLOW HERE
val tx = Transaction()
tx.start()
someEntity.save() // YES, ALLOW
tx.commit()
someEntity.delete() // DO NOT WANT TO ALLOW HERE
How do I make them appear and disappear in the correct context?
Note: this question is intentionally written and answered by the author (Self-Answered Questions), so that the idiomatic answers to commonly asked Kotlin topics are present in SO. Also to clarify some really old answers written for alphas of Kotlin that are not accurate for current-day Kotlin. Other answers are also welcome, there are many styles of how to answer this!
The Basics:
In Kotlin, we tend to use lambdas passed into other classes to give them "scope" or to have behaviour that happens before and after the lambda is executed, including error handling. Therefore you first need to change the code for Transaction to provide scope. Here is a modified Transaction class:
class Transaction(withinTx: Transaction.() -> Unit) {
init {
start()
try {
// now call the user code, scoped to this transaction class
this.withinTx()
commit()
}
catch (ex: Throwable) {
rollback()
throw ex
}
}
private fun Transaction.start() { ... }
fun Entity.save(tx: Transaction) { ... }
fun Entity.delete(tx: Transaction) { ... }
fun Transaction.save(entity: Entity) { entity.save(this) }
fun Transaction.delete(entity: Entity) { entity.delete(this) }
fun Transaction.commit() { ... }
fun Transaction.rollback() { ... }
}
Here we have a transaction that when created, requires a lambda that does the processing within the transaction, if no exception is thrown it auto commits the transaction. (The constructor of the Transaction class is acting like a Higher-Order Function)
We have also moved the extension functions for Entity to be within Transaction so that these extension functions will not be seen nor callable without being in the context of this class. This includes the methods of commit() and rollback() which can only be called now from within the class itself because they are now extension functions scoped within the class.
Since the lambda being received is an extension function to Transaction it operates in the context of that class, and therefore sees the extensions. (see: Function Literals with Receiver)
This old code is now invalid, with the compiler giving us an error:
fun changePerson(person: Person) {
person.name = "Fred"
person.save() // ERROR: unresolved reference: save()
}
And now you would write the code instead to exist within a Transaction block:
fun actsInMovie(actor: Person, film: Movie) {
Transaction { // optional parenthesis omitted
if (actor.winsAwards()) {
film.addActor(actor)
save(film)
} else {
rollback()
}
}
}
The lambda being passed in is inferred to be an extension function on Transaction since it has no formal declaration.
To chain a bunch of these "actions" together within a transaction, just create a series of extension functions that can be used within a transaction, for example:
fun Transaction.actsInMovie(actor: Person, film: Movie) {
film.addActor(actor)
save(film)
}
Create more like this, and then use them in the lambda passed to the Transaction...
Transaction {
actsInMovie(harrison, starWars)
actsInMovie(carrie, starWars)
directsMovie(abrams, starWars)
rateMovie(starWars, 5)
}
Now back to the original question, we have the transaction methods and the entity methods only appearing at the correct moments in time. And as a side effect of using lambdas or anonymous functions is that we end up exploring new ideas about how our code is composed.
See the other answer for the main topic and the basics, here be deeper waters...
Related advanced topics:
We do not solve everything you might run into here. It is easy to make some extension function appear in the context of another class. But it isn't so easy to make this work for two things at the same time. For example, if I wanted the Movie method addActor() to only appear while inside a Transaction block, it is more difficult. The addActor() method cannot have two receivers at the same time. So we either have a method that receives two parameters Transaction.addActorToMovie(actor, movie) or we need another plan.
One way to do this is to use intermediary objects by which we can extend the system. Now, the following example may or may not be sensible, but it shows how to go this extra level of exposing functions only as desired. Here is the code, where we change Transaction to implement an interface Transactable so that we can now delegate to the interface whenever we want.
When we add new functionality we can create new implementations of Transactable that expose these functions and also holds temporary state. Then a simple helper function can make it easy to access these hidden new classes. All additions can be done without modifying the core original classes.
Core classes:
interface Entity {}
interface Transactable {
fun Entity.save(tx: Transactable)
fun Entity.delete(tx: Transactable)
fun Transactable.commit()
fun Transactable.rollback()
fun Transactable.save(entity: Entity) { entity.save(this) }
fun Transactable.delete(entity: Entity) { entity.save(this) }
}
class Transaction(withinTx: Transactable.() -> Unit) : Transactable {
init {
start()
try {
withinTx()
commit()
} catch (ex: Throwable) {
rollback()
throw ex
}
}
private fun start() { ... }
override fun Entity.save(tx: Transactable) { ... }
override fun Entity.delete(tx: Transactable) { ... }
override fun Transactable.commit() { ... }
override fun Transactable.rollback() { ... }
}
class Person : Entity { ... }
class Movie : Entity { ... }
Later, we decide to add:
class MovieTransactions(val movie: Movie,
tx: Transactable,
withTx: MovieTransactions.()->Unit): Transactable by tx {
init {
this.withTx()
}
fun swapActor(originalActor: Person, replacementActor: Person) {
// `this` is the transaction
// `movie` is the movie
movie.removeActor(originalActor)
movie.addActor(replacementActor)
save(movie)
}
// ...and other complex functions
}
fun Transactable.forMovie(movie: Movie, withTx: MovieTransactions.()->Unit) {
MovieTransactions(movie, this, withTx)
}
Now using the new functionality:
fun castChanges(swaps: Pair<Person, Person>, film: Movie) {
Transaction {
forMovie(film) {
swaps.forEach {
// only available here inside forMovie() lambda
swapActor(it.first, it.second)
}
}
}
}
Or this whole thing could just have been a top level extension function on Transactable if you didn't mind it being at the top level, not in a class, and cluttering up the namespace of the package.
For other examples of using intermediary classes, see:
in Klutter TypeSafe config module, an intermediary object is used to store the state of "which property" can be acted upon, so it can be passed around and also changes what other methods are available. config.value("something").asString() (code link)
in Klutter Netflix Graph module, an intermediary object is used to transition to another part of the DSL grammar connect(node).edge(relation).to(otherNode). (code link) The test cases in the same module show more uses including how even operators such as get() and invoke() are available only in context.

Call child class method using dynamic keyword

I have several classes all implementing an interface IBar. Those classes are BarA, BarB, BarC.
I also have a base class Foo:
abstract class Foo
{
void Do(IBar bar)
{
Handle((dynamic)bar);
}
void Handle(IBar bar)
{
Console.Out.WriteLine("Fallback Scenario");
}
}
I want a child class FooChild like follows:
class FooChild : Foo
{
void Handle(BarA bar) {
Console.Out.WriteLine("Handling BarA");
}
void Handle(BarB bar) {
Console.Out.WriteLine("Handling Bar");
}
}
No I want to do the following, but I don't get the result I expect
var foo = new FooChild();
foo.Handle(new BarA()); // expected: Handling BarA, actual: Fallback Scenario
foo.Handle(new BarB()); // expected: Handling BarB, actual: Fallback Scenario
foo.Handle(new BarC()); // expected: Fallback Scenario, actual: Fallback Scenario
I can solve it by moving the Do(IBar bar) method to the FooChild class, but I don't want to do that. I might have 10 Foo childs and don't want to repeat that code. Is there a solution for this?
I think you want this:
void Do(IBar bar)
{
dynamic dynamicThis = this;
dynamicThis.Handle((dynamic) bar);
}
That way the method will be found against the actual type of this. Otherwise, the compiler remembers that the method was called from Foo, and only treats the argument dynamically, finding methods which would have been available from Foo with the actual type of bar. You want methods which would have been available from the actual type of this, as well as using the actual type of bar (via the cast to dynamic).
(You'll need to make the Handle methods public though.)

Resources