I am having this error:
#Override
public void paint(Canvas canvas) {
}
The method paint(Canvas) of type MainActivity must override or implement a supertype method.
The error disappears only if I remove the #Override before the method.
I have already set in project properties java compiler on level 1.6
Can you help me?
If you are extending an Activity you can't override the paint method.
Paint is not an Activity method. You can only override existent methods from the class you are extending.
Also I never used Paint. Did you want to override the onDraw(Canvas) from the View?
It seems you are trying to override a method that doesn't "exist" in MainActivity's superclass.
Some possible reasons (and solutions):
You forgot to add extends ... to the class you think it (MainActivity) inherits from.
You confused the method name, and it shouldn't be paint() - if this is the case - just change the method name
It is a new method for this class - and the annotation #Override should be deleted.
You changed the arguments for the original method - and you are overloading instead of overriding. You should stick with the same arguments if you really want to override it, or remove the #Override annotation if you are after overloading.
if indeed the method that you want to override exists in the parent class then make sure you are compiling with at least java 1.6
So left click on your project -> properties -> Java Compiler -> Select at least java 1.6 then clean the project and rebuild.
Related
I have a class that extends another, but in this class I do not want to call the super constructor.
How can I solve it?
Here is a snipet of my code
class SubarticlePagerAdapter(fragmentManager: FragmentManager, context: Context, var selectedArticleName: String) : ArticlePagerAdapter(fragmentManager, context) {
var subarticleDao: ArticleDao
var itemCount = 0
init {
ApplicationHelper().getApplication(context).appComponent.inject(this)
subarticleDao = ApplicationHelper().getApplication(context).subarticleDaoSession.articleDao
initBundles(context)
}
override fun initBundles(context: Context?) {
}
}
My problem, when this constructor is called, parent class constructor run first, and initBundles() will be called from there, but at that time subarticleDao and selectedArticleName are not set and I get exception.
TL;DR
I'd advise you to move the code from the init block to the initBundles function and use your variables there after initialization. Then there would be no need to avoid calling the superclasses constructor.
Extensive Answer
I think you should think about what you want to do with your design. Working around the idioms of a language is not very often a good idea or a sign of good design - at least when kotlin is your language :)
What you did with your code (overriding a - possibly abstract - method, initBundles from your superclass is pretty much the template method pattern. So it seems to me the purpose of initBundles is to let subclasses customize parts of the initialization... What basically is what you do in your init block.
EDIT: As Paul pointed out in the comments, you can't use the member selectedArticleName before your base classes initialization has finished. So if the base class calls initBundles during its initialization, then properties in the subclass won't be initialized as also stated at Paul's link.
Since in the snippet you don't use selectedArticleName, you could just move your initialization stuff to the initBundles function and init your subarticleDao there.
However, if you need to use your subclasses properties at that point, I'd really advise you to rethink your design. There should be several ways to solve this, but to decide what would suits your requirements best one would need further insight into the intentions you have with your design.
This question already has answers here:
Kotlin : safe lambdas (no memory leak)?
(3 answers)
Closed 5 years ago.
I have a piece of simple code below in an activity...
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
}
});
valueAnimator.start();
}
}
If the activity got terminated, there will be memory leak (as proven by Leak Canary).
However, when I covert this code to identical Kotlin code (using shift-alt-command-k), it is as below
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val valueAnimator = ValueAnimator.ofFloat(0.0f, 1.0f)
valueAnimator.repeatCount = ValueAnimator.INFINITE
valueAnimator.addUpdateListener { }
valueAnimator.start()
}
}
Memory leak no longer happen. Why? Is it because the anonymous class object got converted to Lambda?
The difference between these 2 versions is pretty simple.
Java version of the AnimatorUpdateListener contains implicit reference to the outer class (MainActivity in your case). So, if the animation keeps running when the activity is not needed anymore, the listener keeps holding the reference to the activity, preventing it from being garbage-collected.
Kotlin tries to be more clever here. It sees that the lambda which you pass to the ValueAnimator does not reference any objects from the outer scope (i.e. MainActivity), so it creates a single instance of AnimatorUpdateListener which will be reused whenever you [re]start the animation. And this instance does not have any implicit references to the outer scope.
Side note: if you add the reference to some object from outer scope to your lambda, Kotlin will generate the code which creates a new instance of the update listener every time the animation is [re]started, and these instances will be holding the implicit references to MainActivity (required in order to access the object(s) which you decide to use in your lambda).
Another side note: I strongly recommend to read the book called "Kotlin in Action" as it contains lots of useful information on Kotlin in general, and my explanation of how Kotlin compiler make a choice about whether to put the implicit reference to outer scope into the object created after SAM conversion or not comes from this book.
1. Check what's actually going on
I think you'll find the “Show Kotlin Bytecode” view very helpfull in seeing exactly what is going on. See here for the InteliJ shortcut.
(Would have done this for you, but hard without greater context of your application)
2. JVM similarities, but Kotlin explicit differences
But since Kotlin runs on the same JVM as Java (and so uses the same garbage collector as Java) you should expect a similarly safe runtime environment. That being said, when it comes to Lamdas and explicit references, when they're converted. And it can vary in different cases:
Like in Java, what happens in Kotlin varies in different cases.
If the lambda is passed to an inline function and isn’t marked noinline, then the whole thing boils away and no additional classes
or objects are created.
If the lambda doesn’t capture, then it’ll be emitted as a singleton class whose instance is reused again and again (one class+one
object allocation).
If the lambda captures then a new object is created each time the lambda is used.
Source: http://openjdk.java.net/jeps/8158765
3. Summary, and further reading
This answer should explain what your seeing, couldn't have explained it better myself: https://stackoverflow.com/a/42272484/979052
Different question, I know, but the theory behind it is the same - hope that helps
As you already suggested, the argument to addUpdateListener is actually different in both versions.
Let's see an example. I've created a class JavaAbstract with a single abstract method foo:
public interface JavaInterface {
void foo();
}
This is used in JavaInterfaceClient:
public class JavaInterfaceClient {
public void useInterfaceInstance(JavaAbstract inst){
inst.foo();
}
}
Let's see how we can call useInterfaceInstance from Kotlin:
First, with a simple lambda as in your example (SAM Conversion):
JavaInterfaceClient().useInterfaceInstance {}
The resulting bytecode represented in Java:
(new JavaInterfaceClient()).useInterfaceInstance((JavaInterface)null.INSTANCE);
As you can see, very simple, no object instantiations.
Second, with an anonymous instance:
JavaInterfaceClient().useInterfaceInstance(object : JavaInterface {
override fun foo() {
}
})
The resulting bytecode represented in Java:
(new JavaInterfaceClient()).useInterfaceInstance((JavaInterface)(new JavaInterface() {
public void foo() {
}
}));
Here we can observe new object instantiations, which defers from the SAM conversion / lambda approach. You should try the second example in your code.
I'm creating interface and some function in it has a body.
It's required, that class that implements this interface must call super in overriding function before executing other code.
How can I do this?
interface Watcher {
fun funWithoutBody()
fun startWatching() {
//do some important stuff which must be called
}
}
I've accidentally found, what I was looking for. It's a #CallSuper annotation available in androidx.annotation package. Docs
Use the #CallSuper annotation to validate that an overriding method
calls the super implementation of the method. The following example
annotates the onCreate() method to ensure that any overriding method
implementations call super.onCreate():
#CallSuper
protected fun onCreate(savedInstanceState: Bundle?) {
}
Android Studio / IntelliJ IDEA does this sort of thing in some cases but it isn't done through annotations but through code inspection.
e.g. MissingSuperCall is an Android Lint Check for which IntelliJ IDEA supports (Integration with Android Lint tool in IntelliJ IDEA 11.1 | IntelliJ IDEA Blog).
You can create your own custom inspection if you are using Android Studio or IntelliJ IDEA: IntelliJ IDEA 2016.2 Help :: Creating Custom Inspections.
You could just make startWatching abstract and call it in another function. E.g.:
interface Watcher {
fun funWithoutBody()
fun userDefinedStartWatching()
fun startWatching() {
//insert code you'd normally want to be called when using super()
userDefinedStartWatching()
}
}
I am trying to you use Android Annotations (https://github.com/excilys/androidannotations) in an existing project. I cannot convert the whole project to use Annotations. Can I have some activities that utilize annotations and some acitivites that doesn't use Annotations.
But When I did that, some functionalities stopped working. Like If I used only -
#ViewById(R.id.find)
public Button FIND;
...
...
#Override
protected void onCreate(Bundle savedInstanceState) {
...
if (FIND != null) {
FIND.setOnClickListener(this);
}
...
}
OnClick on the button doesn't work. Is it mandatory to use #Click annotation.
Can't I just use annotations only where I wish to have. And other parts of the code be the old code without annotations. Please guide me.
Thanks
Please read the doc more carefully. The injected views are first available in the #AfterViews annotated methods:
#AfterViews
void afterViews() {
// you can use injected views here
}
https://github.com/excilys/androidannotations/wiki/Injecting-Views#afterviews
First of all please respect coding convention, you can find ax explanation here
Then, for your question, you can use code of both types: native android and android annotations one.
If you inflate a view using #ViewById annotation, you must keep in mind that the injection of the view is done at a certain point of the execution, so before of that your variable will be null.
As WonderCsabo reccommended to you, use injected views inside of #AfterViews annotated method.
Otherwise, if you want to mantain android native syntax, you MUST instantiate your view manually with findViewById method. Obviously after that you have setted activity's layout
I have a around method which tries to hide keyboard on dispatchTouchEvent method.
#Around("execution(boolean (#com.savaskoc.keyboard.KeyboardHide *).dispatchTouchEvent(android.view.MotionEvent))")
This works well if I override dispatchTouchEvent method from android.app.Activity like that
#Override
public boolean dispatchTouchEvent(MotionEvent ev) {
return super.dispatchTouchEvent(ev);
}
Is there any way for intercept parent class' method?
Ps: I tried change "execution" to "call" and it gives;
[warning] advice defined in com.savaskoc.keyboard.KeyboardAspect has not been applied [Xlint:adviceDidNotMatch
I have annotated class named BaseActivity. Around works when I override dispatchTouchEvent like this
#KeyboardHide
public abstract class BaseActivity extends ToolbarActivity {
#Override
public boolean dispatchTouchEvent(MotionEvent ev) {
return super.dispatchTouchEvent(ev);
}
}
but when I remove this method, I'm getting a warning like above
Either you intercept calls instead of executions like this:
call(boolean (#com.savaskoc.keyboard.KeyboardHide *).dispatchTouchEvent(android.view.MotionEvent))
Or, if this is not good enough because calls are being made from code outside the control of your AspectJ compiler, you can continue using execution pointcuts but need to weave aspects into the third party library you want to intercept via binary weaving, creating a new, woven version of it.
Update after Hyperion's edit:
The warning advice ... has not been applied [Xlint:adviceDidNotMatch] simply means that the AspectJ compiler has not found any joinpoints to weave your pointcut into. In this case it means just what I mentioned above when I said:
calls are being made from code outside the control of your AspectJ compiler
This means (repeating myself in other words) that either you have to weave your aspect code into the original JAR containing class ToolbarActivity via binary compile-time weaving or via load-time weaving during runtime, making sure that the aspect weaver is loaded before the original JAR so it can intercept it during class-loading. I have no idea if LTW (or Java agents in general) is available on Android JVMs (I would guess no) because I have never used Android in my whole life, but these two are the options you have. The workaround to override methods you want to intercept always works if all else fails.