Where Do You See Yourself in 5 Years - Why

It may be better in these two years, but back in 2008, people always say Hong Kong is not a good place for tech, especially for web startup. I agree, the whole environment, atmosphere, values put the industry in a big disadvantage. For example, in Hong Kong, you can make better living by doing financial related jobs, and usually have a stabler career path compared to being a programmer.

There is no one to blame. It is normal that a city puts more focus on some area, and has lower priority on others. Yes, HK government sometimes mention IT is one of their important industry, but do you really think the government has what it takes to do anything to help local startup on this fast changing world? I am not judging the government policy/work, I just think it is not their business.

Why stay in Hong Kong

So, why don’t just go? Before I started everything, I had a short internship in Shanghai. As I mentioned in previous post, I was totally not prepared before graduate, so this internship kind of affected how I see the industry and the live of being a developer outside Hong Kong. It was a mixed experience, I did not do well, I can’t say I enjoyed it a lot, but I did open my eye and started thinking how should I go from that point.

I also had an interview in US, it was a no again. I believe I would just leave HK if I got the job and things would go in a completely different way, but I am still proud of what happened next. It sounds like I was stuck in Hong Kong with no choice, there is always choices, I could keep applying but why give up Hong Kong without a try? Even the industry was bad here, I need to know how bad is it.

Why work in startups

From my short internship experience, I learned that if you work in a big team, most likely you will be limited to the tech they already using, it is not a bad thing since you can get deep knowledge in that area, but I was not sure if it was good for me in that time. Touching different latest technologies in development is important to me, it shows how the developers around the world work and keeps you in the trend. You can always try out new stuff in your own time, but as newbie like me, I will need to spend my own time on catching up work. Therefore, working in a (new/small) startup that opens to different technologies would be a best fit to me.

In terms of earnings, working in startup would probably at the bottom of the list amount the jobs required similar skill level. Mathematically you can say you had the possibility of going big in a startup but 0 chance of not doing that. But if this is really the reason of doing startup, you are either very confident in yourself and your team, or you are not go at math…

There is no doubt that I want the startup I am working in goes big one day, but it is not the only thing I care. Besides the result, I value the process even higher. What working in startup means to me is, even you are in a small team and do not have many resources compare to big companies, you can still do something big. To do that, you need to optimize the time, tools, resource you have and keep challenge your team to improve.

What’s next

After working in different startups for 5 years, I think I am still learning and improving as an engineer. I believe someday when I am more experienced and my skill reached certain level, I may have a different view of everything. I am looking forward for what will happen on me and the industry in the next 5 years.

Try Out Quartz Composer and Origami

In late Jan, I watched a talk – Bringing Beautiful Interactions to Android Apps from Facebook about how they use Quartz Composer(QC) when developing Facebok Home (and chat head). Compare to other prototyping tools, QC can better illustrate animations and interactions. It is quite impressive and I actually installed QC the day after and tried to play on it. But when I first opened it, I was totally lost, not saying it is hard to use, but it is obvious that there is a learning curve on this tool. I did not spend more time on it that time but kept it in my TODO list.

Two weeks later, Facebook released Origami, an extension of QC. Followed with some articles about how it is used in Facebook. Yesterday I gave it another try. This time I am more serious compared to last time. My target is at least understand (not fully) how it works and be able to do a simple demo to my team.

Let’s start

This time I started with the documentation, not saying it is poorly documented, but it is not much fun to read it(my bad)… Then I went for tutorials, after a quick look of some articles on QC (not Origami), I had little concept of patches (but missed macro patch…), then I think maybe I can understand the Origami examples.

When I opened the “Photo Grid” example, I only see three patches, I knew that there must be some hierarchy hidden from the interface, I tried to use the patch inspector to look around but have no idea where to go, I was stuck again. Then I found this video on Origami’s twitter, which turned out was everything I needed.

It is the visual version spaghetti code // 6:50

Short notes

  • “Phone” patch is the basic component for the phone prototype, which displays an image in device frame.
  • Use “Render in Image” for the content to display.
  • Double click the “Render in Image” patch to edit the macro patch of it.
  • A “Layer” patch will be automatically added when you drag in an image.

Reference

Where Do You See Yourself in 5 Years - How I Started

5 years ago

Where do you see yourself in 5 years. This was the very first question I got asked in an interview after graduated from university in 2008. I started as a web developer, also touched a little bit iOS. Then I decided to focus on Android and now I am a pure Android developer, nothing close to an expert, but I know what I can do and I am confident in my work.

Of course I did not picture me being Android developer 5 years ago, but other than that, I did foresee myself focused on one area instead of touching everything. Not saying that I am now Android only, but if there is one thing I have better knowledge compare to others in my team, it would be Android.

Source: xkcd

Back in 2008, I enjoyed my 3 years programming competition life and knew absolutely nothing about the real world. I wanted to be a software engineer but had no idea what its like before I graduated (I am not saying it is a bad thing, having work experience before graduate means very little to me, but you may feel a little bit lost at the beginning). I even didn’t prepare for that interview, or you can say, that interview was my preparation of the next interview.

My first reaction on that 5yr question was like, I know nothing about your company, most likely I will not be there 5 years later, what should I say? Is it a trick question? As expected, I did not get the job but this question stays in my head through out the years.

After some friends’ referral and meeting different people, I joined a new, small and passionate “startup + software house” team and started my developer life. I started as a web developer, learning all kind of web tech through client projects, first did some Wordpress theme, then some rails, python and mongodb. Doing projects with different languages and frameworks gave me a chance to play with latest tech outside and most importantly, pushed my learning skill.

Android

Around that time, iPhone was in a very good trend and we started to have some iOS projects. Even I participated in some, I was not a big fan of smart phone as I was already with my computer all day.

In 2010, I got my first smart phone, Google Nexus One, it did not magically changed how I see smart phone in a short time. I actually was still not so convinced by the idea of smart phone in the first few months. What happened was that, one day we decided to play with the Android sdk and build something we want (and simple). This was mainly for fun, and also to let us had a taste of Android development so we might take some Android project in the future.

We decided to make a camera app as side project, because we did see some good camera apps on iOS but those on Android were not compareable to them. Turned out it is nothing close to simple, or I should say, it was one of the hardest thing you can do within the computing power at that time. We spent one week to have our first prototype, everything was ugly, but we just put it on Android market right away. We did not know what to expect, but we were happy to see people actually enjoyed our app. Then I started maintaining the app in my own time and took that chance to catch up with the latest Android development. We learned a lot from building that app, it is a long story so I will not include it here.

Leaving the comfort zone

I stayed in my first company for 3 years. Although we did not go big or have any crazy viral product, we survived, which I think already is an achievement in Hong Kong. I enjoy being a (big) part of the team but I started thinking that 5 years question. I could basically see how I would be if nothing changed and I was not sure if it is what I want. There were other considerations but in short, I decided to leave my comfort zone. I quited my job in early 2012, took a little break and threw myself back to the market.

This time, I started as an Android developer.

A Deeper Look of ViewPager and FragmentStatePagerAdaper

Background

Last week I was working on a remove action on ViewPager, so based on the knowledge from ListView’s adapter, I tried removing the item and called notifyDataSetChanged, it didn’t work. So I googled a little bit and found that I need to override the getItemPosition method in PagerAdapter when removing item.

This is the doc from PagerAdapter

A data set change may involve pages being added, removed, or changing position. The ViewPager will keep the current page active provided the adapter implements the method getItemPosition(Object).

and description of getItemPosition

Called when the host view is attempting to determine if an item’s position has changed. Returns POSITION_UNCHANGED if the position of the given item has not changed or POSITION_NONE if the item is no longer present in the adapter.

Then I put it in my pager adapter, got a different behavior, but still not work correctly. Three thoughts came to me immediately:

  1. something wrong in my getItemPosition
  2. something wrong when I integrate with my other code.
  3. something wrong in FragmentStatePagerAdapter

For 1, it is easy to verify by printing logs and it looked good to me. 2, I don’t think so but still spend some time to check my code first. As expected, problem still existed. I always have a problem with Fragment lifecycle, everytime I thought I understand more, a new problem came out and breaks my understanding of fragment lifecycle. I tried hard to avoid go deep to the implementation of FragmentStatePagerAdapter, but this time I have no choice.

FragmentStatePagerAdapter

I am a little bit surprised by the short code length of it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//https://android.googlesource.com/platform/frameworks/support/+/refs/heads/master/v4/java/android/support/v4/app/FragmentStatePagerAdapter.java
private ArrayList<Fragment> mFragments = new ArrayList<Fragment>();

@Override
public Object instantiateItem(ViewGroup container, int position) {
    if (mFragments.size() > position) {
        Fragment f = mFragments.get(position);
        if (f != null) {
            return f;
        }
    }

    if (mCurTransaction == null) {
        mCurTransaction = mFragmentManager.beginTransaction();
    }

    Fragment fragment = getItem(position);
    ...
    mFragments.set(position, fragment);
    mCurTransaction.add(container.getId(), fragment);

    return fragment;
}

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
    Fragment fragment = (Fragment)object;

    if (mCurTransaction == null) {
        mCurTransaction = mFragmentManager.beginTransaction();
    }
    ...
    mSavedState.set(position, mFragmentManager.saveFragmentInstanceState(fragment));
    mFragments.set(position, null);

    mCurTransaction.remove(fragment);
}

Here is what FragmentStatePagerAdapter does in instantiateItem and destroyItem, in short, it maintains an ArrayList mFragments which mFragments.get(i) returns the fragment that is in position i, null if fragment not in fragment manager. By default, ViewPager will keep one item before and after current item, so if you are at position 1 (0-based), mFragments will be like

0 1 2 3 4
F0 F1 F2 null null

Remove item

What will happen if I remove F1 and call notifyDataSetChanged? the result of getItemPosition should be

1
2
3
F0: 0 (or POSITION_UNCHANGED?)
F1: POSITION_NONE
F2: 1

Right?

Then I expect mFragments become

0 1 2 3 4
F0 F2 null null null

But from the source of FragmentStatePagerAdapter, I don’t think it has any handling of it. I copied the source and added some log to dump mFragments out, and find that it is like

Step What I see 0 1 2 3 4
1 curr item F1 F0 F1 F2 null null
2 after remove F1, F2 becomes curr item F0 null F2 null null
3 swipe next, no item displayed but F4 instantiated null null F2 F4 null
4 swipe next, curr item F4 null null F2 F4 F5
5 swipe next, curr item F5 null null null F4 F5

then the app crashed on step 5 when it tries to destroy F2.

Dafaq?

First of all, what happened in step 2? It just removed F1 and left F2 there, and ViewPager just display it?

Yes, something like that.

  1. When F1 is removed and called notifyDataSetChanged, ViewPager will call getItemPosition for each item, in the order of F0, F1, F2.
  2. When POSITION_NONE is returned for F1, adapter’s destroyItem is called and F1 is removed from FragmentManager and mFragments.
  3. Then for F2, it returned the new position 1, which match the current position, so ViewPager uses F2 directly, but leave mFragments in adapter not updated.
  4. After that, it should create F3 by calling instantiateItem on position 2, however, as mFragments still keeping F2 in position 2, it is directly returned and F3 is never created.
  5. In the first swipe after remove, ViewPager tries to display data in position 2 which the fragment F2 is already used in position 1. At the same time, F0 is removed from FragmentManager, F4 is created as item in position 3.
  6. Second swipe, position 3(F4) becomes current item, position 1(F2) removed from FragmentManager, F5 created for position 4.
  7. Third swipe, position 4(F5) becomes current item, ViewPager tried to destroy position 2, but position 2 is also F2, destroying that cause

    IllegalStateException: Fragment {} is not currently in the FragmentManager.

Workaround

When I tried to isolate the problem, I accidentally return POSITION_NONE for all item, and it actually gave the result I want without crash. It worked because all fragments are destroyed in notifyDataSetChanged and re-instantiated, it does the tricks but may cause other performance problem so I am looking for a better solution.

Possible fix

I have not start yet, but as mFragments in FragmentStatePagerAdapter is private, extending it and override some methods cannot change it at all. Good news is, you can copy the source and compile it yourself.

To fix this, you need to find a way to update mFragments after checking getItemPosition and destroyItem. My initial thoughts is to handle that in finishUpdate(). The new finishUpdate will become something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Override
public void finishUpdate(ViewGroup container) {
    if (mCurTransaction != null) {
        mCurTransaction.commitAllowingStateLoss();
        mCurTransaction = null;
        mFragmentManager.executePendingTransactions();
    }

    ArrayList<Fragment> update = new ArrayList<Fragment>();
    for (int i=0, n=mFragments.size(); i < n; i++) {
        Fragment f = mFragments.get(i);
        if (f == null) continue;
        int pos = getItemPosition(f);
        while (update.size() <= pos) {
            update.add(null);
        }
        update.set(pos, f);
    }
    mFragments = update;
}

One problem is that finishUpdate is also called in other places so need to make sure this change will not break other code and not causing performance issue.

About this post…

At first I just want to write a short notes on the problem I met during work, then I tried to isolate the problem and reproduce it, tried to find similar posts on stackoverflow, read the soure code to confirm the problem, and even tried to fix it… This is totally not my plan for this weekend but I actually quite enjoy reading the source code of support library.

Reference

Useful Features I Missed During Android Development

This weekend, I am working on my Muzei extension and try to add a setting page to it. It is not hard to write everything myself, but I was not in the mood of writing code from scratch, so I just copy code from other opensource project. Modifying other’s code does not always speed up your development when your task is so simple, but you can take this chance to read other’s code at the same time.

I don’t consider myself learned Android development correctly, but I guess most people started like me. I started with a small project, lookup the doc for the features I need, then learn other features while doing other projects.When you learn like this, it is easy to miss out simple features. Here are what I found this week:

Show divider in LinearLayout

Can’t believe I missed this, there was a couple times that I need to append dummy view to act as divider. The worst thing about adding divider view yourself is not the extra code you added, is when you try to control visiblity of elements, you need to handle the dividers also.

1
2
3
4
5
6
7
8
9
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:showDividers="middle"
    android:divider="?android:dividerVertical"
    android:dividerPadding="4dp">
    ...
</LinearLayout>

CheckedTextView

The first time when I want to have checkbox put on the right side of the text, I went through the available options of CheckBox class and cannot find any good, then I go to google and stackoverflow, first solution is to put a TextView to the left of CheckBox. Usually I will just stop here and start coding, but it is obviously not good enoguh, as now you can only trigger it by clicking the checkbox but not the whole text+checkbox.

If you tried the multiple choice feature of ListView, you will see it is exactly the behavior you look for, a little dig in will give you CheckedTextView.

1
2
3
4
5
6
7
8
9
10
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/text1"
    android:layout_width="match_parent"
    android:layout_height="?android:attr/listPreferredItemHeightSmall"
    android:textAppearance="?android:attr/textAppearanceListItemSmall"
    android:gravity="center_vertical"
    android:checkMark="?android:attr/listChoiceIndicatorMultiple"
    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
/>

You can even extend other layout with Checkable interface, more detail here