Android, Kotlin: What exactly is called here? - android

I had Android Studio convert my code for an OnClickListener.
Obviously a lambda is used here. What I don't know is whether the lambda is passed to a function of the View class or to the constructor of the OnClickListener class.
I have already looked in the Android documentation for a method with the name OnClickListener in the View class but found nothing.
If the latter is the case, I don't understand how an instance of the OnClickListener class can be created even though it is an interface.
val onClickListener = View.OnClickListener { refreshListView() }

The class OnClickListener is an inner class of the View class:
https://developer.android.com/reference/android/view/View.OnClickListener
Inner classes are identified by a '.' in their classname, on byte code level they are separated with a '$' instead.
With the invocation as written in your question you create an anonymous class implementing the functional interface and implementing its onClick(View) method. You can do the same in Java with a bit more verbose syntax, but technically the same.

Related

What is the function of an inner class in Kotlin and Android

Please i would like a detailed explanation on what an inner class does what happens in this specific instance. If i dont type out the inner in an inner class of recycleview. calling notifyDataSetChanged() throws an error like this
But if i type inner in front of the ViewHolder Class. The notifyDataSetChanged() error clears
A nested class marked as inner can access the members of its outer class.
Here the class ViewHolder is nested in the class TimeAdapter. So it need to be marked as inner to access to the function "notifyDataSetChanged" of the class TimeAdapter
kotlin inner classes have access to outer class that's why you can call notifyDataSetChanged() method of RecyclerViewAdapter. If you don't make it inner class it doesn't have access to outer class and you can't call outer class method.
Inner make the inner class access the outer class methods
Bek answered you
https://stackoverflow.com/a/65219384/8139353
but i have a simple note about notifyDataSetChanged()
you must avoid using it if you want to update a specific rows
you must use notifyItemChanged(layoutPosition)
this function update only the row you updating
and if you had updated more than one row
you can use notifyItemRangeChanged(layoutPosition, 5)// position and items count
there are many fuctions to use it in adapter like notifyItemRemoved(layoutPosition)

Can I declare a OnClickListener derived class and pass its instance to a view's setOnClickListener method in Frida

In Frida's hooking javascript file,Can I declare a new class which is derived from OnClickListener? I want to pass a new OnClickListener instance to an existing view's setOnClickListener method.
I can get a existing view class as below:
var viewCls = Java.use("com.xxx.myView");
This view does not have any onClickListener in original app. Would it be possible to attach a onClickListener instance to this view through Frida?
I know how to instance an existing class but I do not know how to declare a new class in Frida.
Thanks so much for your suggestion.
I did not find how to declare a new class in Frida. However, I found a workaround to get my requirement done. I share it here and hopefully can help those who met the same issue with me. Basically, what I want to do is to add a onClickListener for a existing View instance. Since we could not declare a new onClickListener derived class in Frida, we can declare it in a separate dex library file. In Frida, we can dynamic load this dex file, find the class, and then new it .The step is as below:
1, Create a java library with your own onClickListener derived class declared. For example:
package com.test.frida
class MyOnClickListener implements onClickListener {
public void onClick() {
//you code here
}
}
2, Compile it to a Android library file, which is assumed as mylib.dex. Then push it to android device.
3, In Frida, assuming the view you want to add onClickListener is appView. We first load mylib.dex as below:
var loader = Java.use("dalvik.system.DexClassLoader").$new(mylib_dex_path, optimizeDir, null, appView.getContext())
optimizeDir should be a directory belongs to the app. It is easy to find a one.
4, Get MyOnClickListener.class and new a instance for it.
Java.classFactory.loader = loader;
var myListenerCls = Java.classFactory.use("com.test.frida.MyOnClickListener");
var listenerObj = myListenerCls.$new();
5, Finally, pass this listener to appView
appView.setOnClickListener(listenerObj);

Do we really need to avoid constructors with default values for Fragments and Activites in Kotlin?

I am great fan of Kotlin and how it allows us to write better code. One of the best features is interface implementation delegation which looks like this:
class A(val someObject:SomeInterface) : SomeInterface by someObject
someObject has to be singleton (object), has to be created using constructor after keyword by (but then you cannot reference to it, or maybe someone has idea how to do it?) or has to be provided in constructor.
In Android messy and bad world we are discouraged to use constructors in fragments and activites due to configuration changes. But how about this:
class MyFragment(val someObject:SomeInterface = SomeObjectImpl()):Fragment,SomeInterface by someObject
I tried to change configuration and event I allowed system to kill my appliction and still, everything is looking ok, my object is creating again and again with my fragment. Is this valid, or am I missing something?
Happy Kotlin everyone!
This is valid. The reason you're discouraged from overloading fragment constructors is that Android can recreate them, and it will use the default one: MyFragment()
But the way Kotlin implements default parameter values behind the scenes is by creating additional constructors. You can decompile your class and see it contains two constructors now, one receiving someObject, and another empty.
From the JVM perspective the empty constructor would look like this:
public A() {
this(new SomeObjectImpl());
}
Calling it will populate your fragment with new instances of implemented classes.

Cannot reference class from another class in same package

I'm admittedly new to Scala and Android programming and in all my searching I haven't been able to find answer to help me understand and resolve my problem.
Here's a gist of my two scala classes https://gist.github.com/Daikamar/f15288a7bf732cd5b55c
I'm running through the tutorial found here: http://developer.android.com/training/basics/firstapp/starting-activity.html
which I'm trying to adapt to scala code (I have need for understanding Scala for work and a personal desire to mess around with Android development so I figured I'd try and combine these efforts).
The problem is seen in DisplayMessageActivity.scala in which the IDE reports that it cannot resolve MyActivity in this line:
val message = intent.getStringExtra(MyActivity.ExtraMessage)
I feel like this should work. I can get it to resolve if I change MyActivity to an object, but then that breaks other pieces of the application that expects MyActivity to be a class.
An help in getting me to understand my problem would be appreciated.
You cannot reference the ExtraMessage field from MyActivity as though it was a 'static' field (in Java terminology). To access ExtraMessage in your other activity you will need to either obtain an instance of MyActivity that you can then de-reference, or add a companion object (defined using the object keyword in the same file in which the class is defined) for MyActivity and define the field there:
object MyActivity {
val ExtraMessage = "net.daikamar.myfirstapp.MESSAGE"
// any other 'static' declarations
}
class MyActivity() extends ...
then your call as above will work.

How to extend two library class in java class android [duplicate]

This question already has answers here:
Extending from two classes
(13 answers)
Closed 9 years ago.
I want to extend two library class files in a java class.How to do this.
You have not given more details about the question.
You can only extend a single class. And implement interfaces from many sources.
Extending multiple classes is not available.
You can use nested classes or inner classes
class A extends B {
private class C extends D {
// A , B , C , D accessible here
}
}
Why Use Nested Classes?
Compelling reasons for using nested classes include the following:
It is a way of logically grouping classes that are only used in one place: If a class is useful to only one other class, then it is logical to embed it in that class and keep the two together. Nesting such "helper classes" makes their package more streamlined.
It increases encapsulation: Consider two top-level classes, A and B, where B needs access to members of A that would otherwise be declared private. By hiding class B within class A, A's members can be declared private and B can access them. In addition, B itself can be hidden from the outside world.
It can lead to more readable and maintainable code: Nesting small classes within top-level classes places the code closer to where it is used.
when to use nested classes
You can find more solutions on this link
Edit
This is an answer to you comment. You want to call method of outer class in inner class. This is an example.
class Outer {
void show() {
System.out.println("inside outter show");
}
class Inner{
void show() {
Outer.this.show(); //this is calling Outer class method into Inner class
Example e = new Example(); //create object of another class
e.show(); //call to method
System.out.println("inside inner show");
}
}
public static void main(String[] args) {
Outer o = new Outer();
Inner i = o.new Inner(); //create an object of Inner class
i.show(); //this is calling Inner class method from outside method
}
}
class Example
{
void show()
{
System.out.println("inside example show");
}
}
Output:
inside outter show
inside example show
inside inner show
Unfortunately in JAVA you can only extend a single class that means each Class can only extend one class. you can implement many interfaces but not extend.
however there are ways in which you can sort of surpass it, you can just make the libs public and then include them so you could create an instance and use their functions, you can create an inner class and use it for whatever purposes you need...
you can also create a chain of extension like:
public class A extends Activity
public class B extends A
so B will extend both...sort of
its hared to give you a working solution when we dont exactly know the issue,do you mean adding support libs? adding SDK? or really extending two classes (which is impossible straight forward).
#Aniket gave you an example of how to work around it so to speak...
hope I helped
sorry for the bad news:)

Categories

Resources