How to make in page margin animations smooth for ViewPager pages

tl;dr modify the setOffScreenLimit dynamically.

In order to keep a constant length ViewPager scrolls smooth, setOffScreenLimit(page.length) will keep all the views in memory. However, this poses a problem for any animations that involves calling View.requestLayout function (e.g. any animation that involves making changes to the margin or bounds). It makes them really slow (as per Romain Guy) because the all of the views that's in memory will be invalidated as well. So I tried a few different ways to make things smooth but overriding requestLayout and other invalidate methods will cause many other problems.

A good compromise is to dynamically modify the off screen limit so that most of the scrolls between pages will be very smooth while making sure that all of the in page animations smooth by removing the views when the user. This works really well when you only have 1 or 2 views that will have to make other views off memory.

@Override
public void onPageScrollStateChanged(int state) {
if(state==ViewPager.SCROLL_STATE_IDLE){
if(mViewPager.getCurrentItem()==INDEX_OF_ANIMATED_VIEW){
mViewPager.setOffscreenPageLimit(1);
}else{
mViewPager.setOffscreenPageLimit(OLD_PAGE_LENGTH);
}
}
}

Cooper is far from dead

Cooper Union

Yesterday, Cooper Union's administration has announced that Cooper will no longer offer 100% free scholarship starting with the incoming freshman in fall 2014. It will still be need-blind admission, but it will charge those who can afford it up to 50% of the full price (around $20,000). 

Within one hour, my Facebook feed has blown up with almost every classmate of mine posting something related to it and how "Cooper has died". 

I am not a fan of the decision that the administration has came up (I am just like everyone else who wish the school can be free forever), but I certainly do think that this will eventually happen, and it is one of the best ways that it could have turn out. If this can last forever, that we can still pay for those who cannot afford, why not? I understand that the whole vision of Cooper's mission that "Education should be free as air and water" but in difficult times, why not let the rich chip in a little bit? The bloated administration is another issue: this is not something that is easy to cut down. It's just unrealistic. 

RIP the Free Cooper Union....

But Cooper has not died. Yes, admission rate will go up a bit. Yes, there will be those who would otherwise attend Cooper attend MIT or Harvard. MIT is not free, so why is it so competitive? It's not because it is free, it's because it has the reputation to be one of best schools in the world and producing the best talents in the respected fields. Therefore, theoretically, if Cooper alums like me and you keep doing the best we can do succeed in our fields, we will be able to compensate some of the "reputation" that Cooper have lost from the scholarship reduction.  

Only with alum and faulty support may we one day get the full scholarship back. Or maybe we will never get it back, but we still have to keep the place that has given us such a unique opportunity, to stay alive. 

Another selfish wish I have is that future alums, who may have to pay some of his/her tuition, will also appreciate Cooper and feel grateful that he/she didn't have to pay 50k/yr for college. Cooper is not purely defined by it's free tuition, but also the quality and the experience it gives. 

Go start your company fellow Cooper kids, let's make the next Facebook and get the free tuition tradition back. :) 

Becoming a better programming

I think I'm going through different phases of becoming a better programmer these days and the feeling is really good.

Sources to improvement:

1. School: CS background, knowing how to break a problem down and analyze the strategy to solve it.

2. Working on side projects for fun in school: free learning, time management, experience the joy. This source also get you the most rewards. 

3. Working with a large team at a big company: you learn bureaucracy and how large companies maintain code and process. Y

4. Working at a mid size company with a small team: you learn how to manage your own time since you won't have a manager. You learn to maintain your code better as the company grows.

5. Working at a tiny company you started: stressful, but rewarding. At this point you just write things that works, but the good habits developed from #4 really helps.

6. Working as an independent contractor: time management+fast coding+ coding for yourself+half managed style.

7. Back to working at a startup with a rockstar team. :)

Endroid's local comm done. :)

Since school has ended for me last month, I started on Endroid, an experimental project for me to build a self-ware robot (project plan).  

So far, the easy mechanical parts are done:

The Vex 2-wire motors can be controlled via Arduino fairly easy with Vex Microcontroller 29 which turns Arduino's PWM (pulse width modulated signals) into DC signals so you can plug them directly into the PWM analog ports and write the programs using Servo.h class. 

The are only two parts that I think were tricky to me since I am a beginner in making physical toys: first is the power source, you can't power the motors using a 3V or 5V motor, so what you can do is power the motors separately using a 7.5V or 9V battery, the reason for this goes will be explained again later as well.

The second part is the value for moving forward/stop/backwards when using Servo.h in Arduino, the following values were tested:

const int MF = 20;  // angle that moves motor forward
const int MB = 138; // angle that moves motor backward
const int MS = 91; // angle that stops the motor

(well, switch to #define for you code of course)

Then for the Aruidno and Android connection, you will first have to download and follow the instructions for Demokit for ADK 2.0. 

A stripped down version below that allows you to control the robot moving in different directions via an Android device (3.0+) can be found below. I have omitted layout xmls and manifest since they are fairly straight forward. Credits also goes to various online sources and Stack Overflow. 

Looking forward

2012 is almost over.  Many key life events has happened to me, graduation from college, finding my first full time job (Squarespace), getting funded for my startup (NYU to SleepBot), and ended with a death of a close family member. It was a very busy year and I certainly hope it had ended better.

Looking forward to 2013, I will try to make the best of it with Jane, together. Now that I am done with school, I can focus more on SleepBot and continue preparing to start on my robotics stack.

If the world does not end in a week, next year will be the best.

Can't live without git any more

Thanks Linus for writing the stupid content tracker [1] for the 1 millionth time. Just pinned down the exact line that were committed into the repo from two weeks ago within an hour that may take hundreds of hours of work if it was not version controlled using git. (even if it was using SVN will use 2-5x the hour) :)

[1] try "man git" on a POSIX system.

Why I choose Cooper Union

Four years ago, I choose Cooper Union over all the other schools....including UC Berkeley and various top schools. Today, I'd say that it was probably one of the best decisions I have ever made. To honor my decision I agreed to write a small piece on "US News Best College 2013 Edition". Hope it will help Cooper to continue to get best applicants. :) 

Not to my surprise, Cooper is once again #1 in the North and the computer/electrical engineering program ranked #2 in the country, with one of the lowest acceptance rates in the country (on par with Harvard, MIT, Stanford..).

Congrats! 

The real problem with using HTML5 for native apps

Yes, lagging is such a big problem right now with HTML5 and there is much heated debates (most recent on on HN) going on in the tech community, the advocates say that the biggest advantage is to allow "one code base for the same damn thing on multiple devices" while others say that it is not ideal yet because of speed.

Yes, speed is a big problem, but as we follow Moore's Law (and hopefully Koomey's Law as well), speed problems will go away even if Apple/Google tries to retard the mobile browsers (which IMHO they won't). 

The real problem is that the same damn codebase cannot be used on multiple platforms. 

It just can't. Look at all the complaints Intagram got for its Android release because it didn't follow major Android guidelines. One of the major issues was the bottom tab bar. In iOS, that is totally ok, but for Android that is not an idea solution as the virtual/hardware keys are also right below. And this is just one of the major problems with fitting it. 

When we started designing SleepBot for iOS, we looked at so many apps for both platforms, and there are just so many differences that we have to do redesign almost all the major interactions and icons. (Notice how icons have a "realistic feel" in iOS, a modern feel in Android, and a futuristic feel in Windows Phone) 

That is Android, now let's take a step forward to Windows Phone 8. Can you even imagine directly porting an iOS app to it. It would look like SHIT and usability would be terrible because that is simply not how it works.  

What's gonna end up happening is that developers will start writing native bridges for performance tweaks and UI tweaks. These developers are usually not experienced in doing those as they usually have a web app background, so it ends up either wasting more time and more resources, for something worse.

Someone may argue that there will be "plugins" that will provide awesome native compatibility. Yea, I'd give those a shot, but good luck customizing your app. :)

If you want the best user experience for your users, at least within the next 5 years, go native.

(note: this is not about having a mobile version of your website and very simple one page apps that does not require complex navigation etc )

P.S. If there is really someone that may disrupt everything, look at Parse's new feature:

http://blog.parse.com/2012/09/11/welcoming-cloud-code-to-the-parse-family/

Bug of the month

This one literally took me days to figure out: http://stackoverflow.com/questions/11836468/fragmentpager-not-updating-views

The problem was that Google had inconsistency (which is expected) between its Fragment classes and Support Library's Fragment classes that some of the methods are not implemented and also not well documented.  In this case, destroyItem() was not properly implemented, so that it doesn't matter what other methods you override. Ended up almost reimplementing the whole class. :)

Just want to complain a bit here because it really took a good amount of time. Hopefully the support library will get better soon.

Back from China. :) Feel free to hit me up. (All the posts following this will be for testing purposes)

My goal for 2012

Give back to the open source world.

Why? I have this sudden feel that I have simply taken too much from all the open source projects and that I have not been able to really contribute to any of them yet. I feel that I have owe too much to all the open source developers (100% of SleepBot is built on open source technology). So my goal for 2012 will be contribute to a few open source projects, or open source some tools and patterns I developed in the past.  :) 

Happy coding.

Two sleepless days

The last two days has been crazy:
Wednesday: Initial launch of mysleepbot.com (we still have lots of links to fill in), working on my quantum physics hw...until 6am. 
Thursday: Woke up at 8am to attend NY Tech Day (SleepBot was sponsored by NYC Rails to be there). Talked non-stop to hundreds of people with Jane and Dan. Got home and worked on Squarespace's iOS/Android apps. Then fixed some things on mysleepbot.com to make it look nice on IPad....slept around 7am. 
Friday: Woke up at 9 to pitch at NYU. I stayed until the award ceremony (WHICH WE WON!!!). Now I am at Squarespace. :) I guess it was worth it. ..but the final pitch event is the same day as my physics final. so idk. 
.....This weekend: essays, physics hw, preparing for next week's interview at SF, working on the new project, and keep making SleepBot more awesome. 

Oh and did I say Jane is awesome? She didn't sleep at all in the past two days to work on the website and the pitch deck. :)

me and dan

me and dan

Web As a Shell

----------------------
Web As a Shell is a shell that that lives inside your browser to run API calls to different web services. It runs on WebSQL and many cool open source libraries. It was inspired by the try.mongodb.com.  
GitHub: http://edisonw.github.com/Web-as-a-Shell 
Disclaimer: This is one of those projects that you just use it for fun and not intended to have much practical usage.
-----------------------

Features:

  1. User system: you can create and login as different users. After you login, everything saved as a user's preference will be encrypted by a encrypted key that is encrypted by your password. (similar to how SSL works) The password is only persisted in each session. 
  2. A modular drop in handler system: To make a new command, simply make it and drop it into the /js/handlers folder. Every time you call a command, it will be initialized and downloaded at that time. If you have updated the handler, you just have to call the reload command. 
  3. File system and built-in support for Dropbox (not done yet): Can authenticate with Dropbox with a api key/secret (that you can store encrypted in your user preference); list the files, and download or upload certain files. Files can be saved in base64 as user preferences and use to upload to other web services. *support for lstat etc in the future?
  4. Twitter handler that posts and checks twits via web-shell's command line.  (planned)
  5. ...only works in Chrome at the moment. 

Ajax loading: Handling duplicate Ids with JQuery.

As single page web apps getting popular, there's often one problem: when a user goes to another page and goes back while all were done with ajax, some items will be left behind. 

This happens when an item gets created outside of the container that gets loaded, so JQuery's .html() would replace what was in the old container. However, sometimes because of some third party library you use, there may be appended elements that is outside of the tag or they may have moved some elements to the bottom of the page (i.e. JQuery UI's dialog boxes). This is really annoying because you will end up with duplicate items. So next time when you want to call up a specific item with certain ID, you will get the old one that will be hidden from the user.

The trick here is to tag every class that you inject with with a special class, say "injectedItem", now before you replace the old html with a new page, you call $(".injectedItem").remove() to remove all the proper elements. Note that you don't have to tag the elements that you are sure that will be removed properly under .html(). 

Ajax loading: No Hashbangs, just HTML5

Hashbangs (#!) has been around the web for a while now since Twitter started using it for Ajax page loads. I was rather annoyed by the unnecessary page refreshes from time to time. But noooow...Twitter is finally starting to move away from hashbangs! I remember talking to the front-end engineer at Twitter a few months ago at their San Francisco headquarter with it and asked them why they did it.  It was when I was working on the menu's for SleepBot. After I came back to New York, I wanted to implement it for SleepBot. However, it turned out that it is not that simple to parse out the URL's hashbang after all and press was there for us to release it on time.

So I ended up using History.js, a Javascript wrapper for HTML5 history management: on the links that uses ajax load, we bind the click with the following if statement:

if(History.enabled){
//Do the ajax load, and then use History.pushState(....) to update the url
}else{
//IE users, I'm sorry, you are getting a cold refresh. 
}

This worked at first, however, as the project grows, problem happens with Ajax load: bindings stopped working! It was caused by my lack of understanding for jQuery's bind live and delegate functions. If you are serious about web development using jQuery, that is a must read. 

SleepBot Synchronization

Since we started planning for a web platform for SleepBot, the biggest problem I had was how to efficiently synchronize the data people already have on their phone with the central database. 

The simple part: When a user sign in on their phone, all the existing data on the phone are transmitted to the server. The server would first get all the data the user has that already on the server, match the ones that needs to be updated (base on their last modified time) and insert the ones that are missing. The ones that are missing or updated on the device will be sent back. The device would then verify the data, and if there are no error, mark the last updated time.

Now there are a few different things that can happen:

  1. User punched in on the website. 
  2. User edited/updated sleep data on the website.
  3. User punched in on the phone.
  4. User edited/updated sleep data on the website.

For Android 2.2 or above devices that have C2DM enabled, we can use push notifications:

  1. For case 1 and 2, SleepBot will queue all the updates on the server and send updates to the devices via push notifications. 
  2. For case 1, I call it a state change, in which the user has to see immediately on their phone, so when a device receive a notification on case 1, it will try to synchronize immediately, if possible. If any error happens, the device will mark itself as "needs to be updated". When the user opens SleepBot, the device will try to contact with the server again for updates. In these exchanges, the last update time will be used to only exchange the modified entries.
  3. For case 2, SleepBot will only mark the device as "needs to be updated", this way in case there are more updates, only one update will happen until user open SleepBot again on their phones. 

For Androids that does not support push notification (Kindle Fire, Android 2.1 or lower) and iOS, SleepBot will try to synchronize every time it is opened.

Regardless of the device, for case 3, SleepBot will synchronize immediately.

Regardless of the device, for case 4, SleepBot will synchronize upon close.

Note that on the server side, whenever a device try to synchronize, it will propagate the changes to all the devices that are connected to the account except the device that requested the synchronization.

At a glance, this is what I came up with. It should cover all the cases.....not sure if this is the most efficient way of handling it though. 

Some thoughts on Nodejs

There are just too many posts aout Node.js these days that lies on the extremes so I want to put my 2c in the pod as well.

My first hand experience with Node.js was when I did my summer internship at Intuit last year. I did an innovation project with it to introduce the language to other developers there in the office.  I ABSOLUTELY loved it. It was very low on memory usage and very easy to code and interact with other web services and it IS fast against apache for simple tasks. But as the code base grows it gets increasingly hard to manage and the chain of callbacks gets messy even if you use awesome libraries such as Step.

Citing from the article from hacker news, "Callback spaghetti is about the last pattern with which you'd ever want to write anything", Also, being a very young language it lacks "dependency injection and proper modularization are actually good things that help you maintain code over time. JavaScript has very little support for any of those nice things: it doesn't even have namespaces" as said in the above link. Node.js, however, in my opinion very fast and low on memory. The place I work for also has done some benchmark and see nearly tenfold increase on output. Companies like Linkedin and Amazon also has made public results of their experience with Node.js that has been very positive. 

Personally, I think Node.js is awesome to develop real time applications that does not require long blocks (process api calls) and it is not ready to use as the primary language yet. You still have to fall back to the more mature languages. 

Happy New Year! SleepBot, and my new web project for fun.

It's been almost a year since I have posted anything here.

2011 was a great year for me.

SleepBot now has over 500,000 downloads and is one of the top rated apps in the Android Market. Jane and I, the SleepBot Team, has just released the web platform to our registered beta testers and friends and families. (https://beta.mysleepbot.com, though to use the App with it you will have to use a special version that supports Sync, and we are not releasing this to the public because we need to monitor the traffic requirements for scale and fix bugs)

It has been a great learning experience building this site. The site is built on Codeigniter PHP framework. It's a great framework: lightweight, powerful, and yet simple. It allowed us to focus on building the real features. However, as the code base gets large, refactor code becomes painful, since PHP is interpreted. Maybe we will switch to Facebook's HipPop, but at this point, we just want to focus on getting a usable product out. There were a lot design decisions to make, and a lot of them were focused on how to do as much as possible on the client side (since we are bootstrapping the costs).

60% of the time ended up building the front-end (JQuery based, though I tend to do things from scratch). This is also something I learned from working at Squarespace(awesome company!).

-Your html body should be with as little in between the tags as possible. -Your back end's job is to spit out a usable JSON so the front-end can parse it into HTML. -So yes, your back-end is mostly a router for the pages and an API server. -Use Ajax to prevent reloading the whole page as much as possible. -CSS is parsed using less.js. -Most environment variables are cached in Apache's process memory.

And this is not possible if it was not pre-2011. Browser supports are much better these days, and clients are usually powerful enough to render the contents without noticeable lags.

The user experience is great on the site, every post, every error message, and every page is carefully designed to maximize UX.

What took 30% of the time was making Sync working between the central server and various devices. There were so many cases to consider, and many different places for code injections. It is the most important part of the site.

For SleepBot, we Android's push notification to either request the client to sync immediately (such as when there's a state change that needs to be reflected) or update when the user opens the app next time. It works beautifully on the few devices that we have tested (2.2 and above). I'm not sure if we are going to ever support non-Google Android devices or just use Urbanairship (It's Helium reports works, but we might just build our own and make it open source...I don't believe this is not something developers should pay for).

One thing that I don't like the most in the process is also be the sysadmin of the project. Setting up servers took too much time from development time.

I did end up teach Jane CSS in the process though. Jane did all the graphic and styling for the site and she did a great job. :) Teaching her about Bash/SSH/Git/basic networking principles....and how she has to git add * and eventually understood it made me very proud of us as a Team!

Oh. and I started on a new project for fun: Web as a Shell (https://github.com/wzsddtc2/Web-as-a-Shell), this is the first project that I have as public repository on GitHub. :) ---In short, it will allow you to execute commands such as : facebook post "Happy New Year" in command line. And the best thing is...it lives inside your browser and requires no server to run. The app is fully built on HTML5, will support basic file IO and have user permission model. Oh, and any one will be able to add any new "Handler" to handle any new commands with a line of code! Detail in my next post. :)