2016-03-11 Drawing is easy

As could be expected, getting back with a fresh mind on the next morning is a good advice. I can now draw a line on the screen – whee-hee! (See the GitHub repo for the code, though it’s really nothing special and still a bit of a mess.)

The less fun part is, I have honestly no idea how I could learn this using the docs/tutorials. What did I do wrong?

First of all, I used ImageView in my layout file instead of my subclass, and I should have had pl.mbork.logeox.DrawingView. Fair enough, this looks reasonable. (This SO answer did help.)

But that I tried yesterday, too, and it didn’t work then. The crucial part was this: in the Java file, I needed something like the following:

package pl.mbork.logeox;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.widget.ImageView;

public class DrawingView extends ImageView {

    Paint paint = new Paint();

    public DrawingView(Context context) {
        super(context);
    }

// The other two constructors are what I missed!!!
    public DrawingView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public DrawingView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawLine(0, getHeight(), getWidth(), 0, paint);
    }
}

It turns out that Android really insists on having those other constructors besides the simplest, one-argument one. Even if they apparently do nothing but call the superclass constructor.

What else can I say? Well, I won’t say “stupid me” – not yet. How could I know? (Well, perhaps I could, but the error messages were not helpful.) What did help me was, in fact, random clicking around: when I switched to the Design tab of the layout editing tab (how Inception-istic!), Android Studio complained that it couldn’t show me the preview due to the lack of the other constructors. Good. Why couldn’t the compiler tell me that? (Or the runtime, for that matter? Read on to learn the answer.)

Most imporantly, what can I learn from this experience? First of all: I never know which constructor will be called, so I need all of them. Second: read the error message very, very carefully. I broke the code again now only to check whether there was a hint in the error message. Well there was. So I will say that after all: stupid me. This is what I got:

03-11 06:03:49.100 20893-20893/pl.mbork.logeox E/AndroidRuntime: FATAL EXCEPTION: main
                                                                 Process: pl.mbork.logeox, PID: 20893
                                                                 java.lang.RuntimeException: Unable to start activity ComponentInfo{pl.mbork.logeox/pl.mbork.logeox.MainActivity}: android.view.InflateException: Binary XML file line #16: Error inflating class pl.mbork.logeox.DrawingView
                                                                     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2298)
                                                                     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
                                                                     at android.app.ActivityThread.access$800(ActivityThread.java:144)
                                                                     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
                                                                     at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                     at android.os.Looper.loop(Looper.java:135)
                                                                     at android.app.ActivityThread.main(ActivityThread.java:5221)
                                                                     at java.lang.reflect.Method.invoke(Native Method)
                                                                     at java.lang.reflect.Method.invoke(Method.java:372)
                                                                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
                                                                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
                                                                  Caused by: android.view.InflateException: Binary XML file line #16: Error inflating class pl.mbork.logeox.DrawingView
                                                                     at android.view.LayoutInflater.createView(LayoutInflater.java:616)
                                                                     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:743)
                                                                     at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
                                                                     at android.view.LayoutInflater.parseInclude(LayoutInflater.java:916)
                                                                     at android.view.LayoutInflater.rInflate(LayoutInflater.java:802)
                                                                     at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
                                                                     at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
                                                                     at android.view.LayoutInflater.inflate(LayoutInflater.java:365)
                                                                     at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:377)
                                                                     at android.app.Activity.setContentView(Activity.java:2144)
                                                                     at pl.mbork.logeox.MainActivity.onCreate(MainActivity.java:20)
                                                                     at android.app.Activity.performCreate(Activity.java:5937)
                                                                     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
                                                                     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251)
                                                                     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360) 
                                                                     at android.app.ActivityThread.access$800(ActivityThread.java:144) 
                                                                     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278) 
                                                                     at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                                     at android.os.Looper.loop(Looper.java:135) 
                                                                     at android.app.ActivityThread.main(ActivityThread.java:5221) 
                                                                     at java.lang.reflect.Method.invoke(Native Method) 
                                                                     at java.lang.reflect.Method.invoke(Method.java:372) 
                                                                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) 
                                                                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) 
                                                                  Caused by: java.lang.NoSuchMethodException: <init> [class android.content.Context, interface android.util.AttributeSet]
                                                                     at java.lang.Class.getConstructor(Class.java:531)
                                                                     at java.lang.Class.getConstructor(Class.java:495)
                                                                     at android.view.LayoutInflater.createView(LayoutInflater.java:580)
                                                                     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:743) 
                                                                     at android.view.LayoutInflater.rInflate(LayoutInflater.java:806) 
                                                                     at android.view.LayoutInflater.parseInclude(LayoutInflater.java:916) 
                                                                     at android.view.LayoutInflater.rInflate(LayoutInflater.java:802) 
                                                                     at android.view.LayoutInflater.inflate(LayoutInflater.java:504) 
                                                                     at android.view.LayoutInflater.inflate(LayoutInflater.java:414) 
                                                                     at android.view.LayoutInflater.inflate(LayoutInflater.java:365) 
                                                                     at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:377) 
                                                                     at android.app.Activity.setContentView(Activity.java:2144) 
                                                                     at pl.mbork.logeox.MainActivity.onCreate(MainActivity.java:20) 
                                                                     at android.app.Activity.performCreate(Activity.java:5937) 
                                                                     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105) 
                                                                     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251) 
                                                                     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360) 
                                                                     at android.app.ActivityThread.access$800(ActivityThread.java:144) 
                                                                     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278) 
                                                                     at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                                     at android.os.Looper.loop(Looper.java:135) 
                                                                     at android.app.ActivityThread.main(ActivityThread.java:5221) 
                                                                     at java.lang.reflect.Method.invoke(Native Method) 
                                                                     at java.lang.reflect.Method.invoke(Method.java:372) 
                                                                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) 
                                                                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) 

Can you spot Wally? Yes, there he is: in the line 40 of this almost 70-line-long error message! Wow, now that’s Java!

Another thing I’d like to share today is my general impression about Android Studio. I kind-of-sort-of like it, but it’s still fairly annoying. The tip-of-the-day is helpful, but I really, really miss quite a few features.

For example, I’ve just found a nice thing under the Help menu, called Help|Productivity guide. It tells me the AS uptime (3 days), and how many times I used code completion and things like that. Very nice… but (there’s always a “but”!) why can’t I copy and paste the text from that window, if only to include it here? Come on - this. Is. Teeeeeeext! Hello! It’s 2016! Text should be copyable!!!

Also, I clicked Help|Online Documentation. Is this a joke? I expected documentation, starting with a table of contents! I had much better luck with Help|Help Topics, which landed me on a nice-looking page about IntelliJ Idea (which AS is based on). Looks good, but (again!) where’s the download button? You expect me to read all this in a browser, online? Seriously? Seems I’ll have a job for wget and Calibre soon.

OK, enough griping. It’s not that bad, I admit. (Though having Control-A select everything instead of bringing me to the beginning of line is annoying. I wonder if I could install at least some basic Emacs keybindings in AS. I’m afraid of a total disaster, though, since they are so different that having only part of a tool use them might end up in a total chaos…)

So today I proudly commited my line-drawing thingy, and the next thing will be the possibility to draw other lines besides the big diagonal. Yay!

CategoryEnglish, CategoryBlog, CategoryMakeYourselfKnown