The ViewHolder Pattern

As you develop your Android application, performance becomes more and more important. If your application appears slow, the user will get frustrated and not want to use it. One example of where this could happen is in the scrolling of a ListView. ListViews are a popular way to display information and can be done very poorly.

Each ListView has an adapter that is responsible for displaying the information in the list, and many times we’ll want to write a custom adapter to do something special. Within that adapter, the getView() method is responsible for figuring out how to display each cell in the list.  There are two main ways you’ll see developers implement this method–the right way and the wrong way.

The wrong way:

public View getView(int position, View convertView, ViewGroup parent) {
    LayoutInflater mInflater = mContext.getLayoutInflater();
    View convertView = mInflater.inflate(R.layout.buddy_list_item, null);
    Buddy buddy = getItem(position);

    ((TextView) convertView.findViewById(R.id.buddy_full_name)).setText(buddy.getFullName());
    ((TextView) convertView.findViewById(R.id.buddy_username)).setText(data.getUsername());
    return convertView;
}

In this example, each time a cell needs to be created, the ListView will need to find the View and its components (see where findViewById() is called?). This means the code will scan over all the layout resources and find this View and get its components to then populate in the cell. This is very expensive, and could lead to poor performance.

The correct way:

public static class ViewHolder {
    TextView fullName;
    TextView username;
}

Now, we use a ViewHolder which will represent a cell in our ListView. The ViewHolder will be attached to the tag field of our View. This will make it much easier for the ListView to recall the correct View and components, rather than calling findViewById() many times. Let’s see how it’s used in the getView() method.

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder;
    if (convertView==null) {
        holder = new ViewHolder();
        convertView = mInflater.inflate(R.layout.list_item_buddy, null);
        holder.fullName = (TextView)convertView.findViewById(R.id.buddy_full_name);
        holder.username = (TextView)convertView.findViewById(R.id.buddy_username);
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    final Buddy buddy = buddies.get(position);
    holder.fullName.setText(buddy.getFullName());
    holder.username.setText(buddy.getUsername());
    return convertView;
}

Here, we only inflate a View from scratch if convertView is null. Otherwise we have a reference to the View through the convertView’s tag, and we don’t need to call findViewById at all! This leads to great performance and smoother scrolling in our list.

Hopefully it’s clear why the ViewHolder pattern is superior. There are some great Android docs that touch on this. If you need clarity or have questions or suggestions, be sure to comment below!

Happy coding!
Brandon from The Bunch

iOS vs. Android: The Case for iOS

iphones

Last week my co-founder Brandon laid out the case for Android. While I agree that Android has some benefits like customizability, there are a few key factors that put the iPhone ahead.

Reliability & Smoothness

The iPhone is a reliable machine that runs at about the same performance throughout its lifetime. There’s a reason iPhone users rarely turn off their phone, and that’s because it performs reliably even after heavy usage. With reliability comes a consistent user experience, providing a smooth user interface. With Android, I’ve seen many phones start out zippy but degrade over time or lag periodically.

Updates

Apple has done a great service to developers and users alike by essentially forcing you to update your phone. Updates are simple on the iPhone, and users are quick to update iOS for new features. For developers, this means they don’t have to support the older versions of iOS, which increases time spent on things that matter. Android phones usually are customized on a phone-by-phone basis, meaning the version of Android they run becomes outdated and doesn’t get updated as frequently, which is bad for developers and users alike and probably only good for new phone sales.

Simplicity

iOS is very consistent and simple across apps. Apple’s design standard has made apps converge on “best” practices (sometimes they might not be the best, but they’re common). An example of this is swiping on an item in a list. The home screen on iOS is quite simple, where each app gets its own space. The counter-point for Android is customizability, but that comes at the expense of simplicity. Personally, I like an environment to be plug and play, where I can start using something and be productive in a matter of minutes and continue to be productive over time. iOS does this well.

Other Benefits

  • Quality of apps (largely due to Apple screening every app in the App Store)
  • Integration with Mac. If you use a MacBook, you’ll agree that some of the desktop apps don’t feel complete unless they’re used with the phone (i.e. Messages, Notes, etc.).
  • The lure of Android is always there to explore something unfamiliar, but I’m a “no-nonsense” user, so you can leave me here…I’ll be ok.

What are you favorite or least-favorite parts about owning an iPhone or an Android? Let us know in the comments below!

Sincerely,
Matt from the Bunch

iOS vs. Android: The Case for Android

android

Which is better: the iPhone or Android? Well, if we say iPhone vs. Android it’s actually as if we’re comparing apples and oranges. iPhone is the name of the device made by Apple. Android is an operating system (OS) made by Google. For the purposes of this blog post, let’s discuss iOS and Android, because there are too many devices that run Android to compare devices, and people usually argue about the OS, not the device it’s running on.

Both operating systems are pretty niche, in my opinion. I believe that’s why this argument can get so heated sometimes. iOS users are typically (in my experience) no-nonsense people who want a quality device that won’t slow them down in any way. This can range from cool hipsters who are more occupied with their other hobbies to worry about a cell phone to older people (like my grandparents) who just want a reliable device to handle the occasional call. Android users tend to be more into tinkering (with a few exceptions here and there). There’s the possibility of rooting the device (gaining root access to the device to bypass certain rules the OS has baked in), and there are undoubtedly more customizations to be made on the Android platform.

So, which is better? I’ve personally owned both. I’ve owned numerous Android devices but temporarily switched to an iPhone 5 for a few years. While there are great things about each, I would like to argue that the Android operating system is superior to iOS. But after you’ve heard my reasoning, you should comment below to let me know what you think!

iOS has a beautiful interface. I will never tell anybody differently. iOS is reliable and quick, all the time. There’s a reason no-nonsense users tend to find themselves on iPhones. iOS is simple. It’s clean. It’s very sexy. There’s no doubt about that. However, for me, this is where it ends. Its simplicity and beauty only go so far for me. I need more.

The Android platform can almost compete with iOS in terms of being clean and beautiful. I’ll admit that it’s not as fast and responsive and can get bogged down under heavy usage. However, this is rare and doesn’t at all ruin the system for me. Where it wins, though, is its customizability. I’m not talking about the ability to root and flash different system images on the devices. And I’m just talking about sheer customization and user experience. When you use an Android, you get the feeling that the phone was made for you. Google Now will tell you where you parked your car, what you wanted to buy at the store (via Wunderlist integration), what your schedule looks like today, how your stocks are doing, how your team did last night, and display articles of interest (that are actually relevant), all on the same screen! Oh, and saying ‘OK Google’ and searching the web actually returns super accurate results, unlike Siri. The great thing about Android is that if you don’t want to customize it or use all of its features, that’s totally fine. The phone still will deliver the same value that an iPhone does.

Also, you can get a phone running the latest Android version for a few hundred bucks, while iPhones cost an arm and a leg.

But this is just my opinion; what do I know? Let me know what you think–and why–by commenting below!

Sincerely,
Brandon from the Bunch

TinyPNG

panda
TinyPNG was used to compress this image and subsequently decrease this page’s load time.

TinyPNG is easily the coolest tool I’ve come across recently. I was looking for an easy way to compress images used on LunchBunch’s website to improve load times, and TinyPNG couldn’t have made it any easier. I’ve compressed PNGs and JPGs (it works with both) with average compression results between 40% and 80% depending on the source and original size. The website is very easy to use too–just upload your images and download a zipped file containing the compressed versions (or optionally save directly to Dropbox). And it works just as well on PNGs with transparency.

Compression is awesome, but what about the quality? PNGs are lossless, meaning that an image won’t change when compressed, but the quality of JPGs deteriorates as the file size shrinks. You don’t have to worry about image quality with TinyJPG–see for yourself at the bottom of TinyJPG’s homepage. The compressed version is barely a quarter of the size of the original, but I can’t tell the difference between the two images!

So after learning all of this, I was hooked. I was excited to use TinyPNG for everything, but what if I want to tinify my images programmatically? Lo and behold, the developer API! With libraries for Ruby, PHP, Node.js, Python, and Java, it is very easy to incorporate TinyPNG into any project. For example, my first attempt in Python was just a few lines:

import tinify
tinify.key = "<your-developer-api-key>"

def tiny(input_filepath, output_filepath):
    source = tinify.from_file(input_filepath)
    source.to_file(output_filepath)

And it just worked!

It seems easy to preserve metadata, integrate with Amazon S3, and even crop/resize before compressing (though I haven’t explored these features yet).

Every once in a while you stumble across a tool that’s exactly what you were looking for. For me, TinyPNG was that and more. If you have a website or use pictures in any way, this is a must-have tool for your project. There’s also a WordPress plugin that is super simple and highly-recommended for your blog.

How do you use TinyPNG in your projects? Let us know in the comments below!

Happy coding!
Ryan from The Bunch

Happy First Birthday!

birthday_cake
One candle for one year; the 44 is for April 4th 😉

The Bunch turns one year old today! 366 days ago, Matt, Brandon, and I had our first video conference to discuss the idea of developing LunchBunch into a fully-realized mobile application. In November of 2015, we launched LunchBunch publicly, and over the past few months, we’ve been updating it and adding new features. It’s time to start growing, so be sure to tell all of your friends about LunchBunch!

I’ve had a ton of fun working on LunchBunch over the past year, and I’d like to thank Brandon and Matt for all of the work they’ve put into making LunchBunch awesome. Seeing the app progress over the past 12 months has been amazing, and their diligence is why LunchBunch has come as far as it has. I couldn’t be prouder of my team and all of the time they’ve devoted to this project.

I especially want to thank you, our blog readers, app users, and general supporters of LunchBunch! This project wouldn’t be possible without you, and we really do appreciate all of the feedback and encouragement you’ve provided along the way. Thanks for cheering us on this past year! With so many exciting changes in the pipeline, I can’t wait to see where LunchBunch ends up on its second birthday!

Sincerely,
Ryan from The Bunch

JodaTime

Time throws a kink in programming sometimes.
Time throws a kink in programming sometimes.

Programmers are no stranger to obstacles, but some seem a lot more daunting than others. Time has been my Achilles heel from the beginning–getting time wrong is a major issue for the front end (and the back end too). If a user thinks their Invitation is set for 4:00PM, but they see 9:00PM on their phone, they’ll be wildly confused! So we as developers have to get this right.

In steps JodaTime, a library with the sole intent of making this struggle a little less of a nightmare.  It’s still no walk in the park, but it’s definitely an improvement. One of the biggest use cases for time is converting between time zones. For instance, you should store all times in your application in one time zone (with the understanding that you have users from different time zones), and then that time is converted to the user’s time zone on the front end.  UTC is the standard that is commonly used for storing timestamps on the back end.

To use JodaTime to convert from UTC to the user’s time, do the following:

DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").withZoneUTC();
DateTime dateTime = formatter.parseDateTime(someStringTime.withZone(DateTimeZone.getDefault();

Of course, there’s more than one way to skin a cat! Head over to JodaTime’s site, and figure out a way that works for you!

Happy coding!
Brandon from The Bunch

Timed Broadcast

hourglass

We’ve been hard at work to bring you new features to enhance the LunchBunch experience, and one of our recent updates modified the way that broadcasting works.

Before our public launch, a user suggested this feature to make it easier to broadcast accurate information. She said she wanted her broadcast to terminate automatically because she didn’t “want to lose [her] LunchBunch integrity.” We thought this was a great idea because it’s easy to forget to switch back to “not hungry” after you’ve eaten.

Timed broadcasts will keep you hungry for one hour before automatically expiring. (Soon you will be able to change this length.) A few minutes before it’s switched off, you will get a push notification asking if you are still hungry with the option to extend your broadcast. Ignoring the notification will terminate the broadcast at the end of the timed period.

Timed broadcasts make it easier for you to use LunchBunch because you don’t need to remember to set your status to “not hungry” after a meal. This also helps hungry buddies know that you are ready to eat (instead of wondering if you simply forgot to edit your broadcast after your last meal).

What do you think of this new feature? Are there any other features we could add to make broadcasting even easier? Let us know in the comments below!

Sincerely,
Ryan from The Bunch

Development and Production Environments

When you’re working on an app that’s live, it’s a good idea to have a development version running that is completely separate from the production version. This way, when things go wrong (and they will), your users are less likely to be affected. Here are three things to consider when separating your production and development environments.

Data

This should go without saying, but the dummy data used in testing shouldn’t be be available in production and vice versa. It shouldn’t even be stored in the same databases. Confining user data to production keeps it safer, and keeping test data out of production makes your live databases cleaner.

Hardware

Keeping separate hardware is wise depending on the type of application you’re running, how many users you have, etc. It’s likely that the required load on the production server will be much higher than the server your team uses for development, so the hardware needs won’t be the same. By separating the hardware, you’re able to scale up and down independently and with minimal impact, and it also helps to reduce the impact of each environment on the other.

Security

Dev servers can have have different authorization permissions to make sure that the right people have access to your application until it’s secure and ready for public use. Security updates and other patches for your OS, libraries, etc. can be issued on your development server without affecting production. That way you can handle upgrade issues on dev and be more prepared when you need to update production.

Two environments is the minimum you should consider configuring for any application. Depending on the size of your team and the nature of the application you’re working on, it’s usually a good idea to have a staging environment which is treated as the most-recent stable development build which is next in line to be pushed into production. It’s also a good idea to have local environments for each developer to work individually without affecting the rest of the team. So the workflow looks like this:

  1. Developers work on their branches locally.
  2. When the local build is ready, it is pushed to dev for the rest of the team to use.
  3. When the dev build is stable, it is pushed to staging.
  4. Once approved by quality assurance and beta testers, the staged build is pushed to production.

This is a very high-level overview of multiple environments, and each project has different needs, so this is in no way a comprehensive writeup about how your pipeline should operate. However, if you’re getting started on a project, I hope this article has given you some ideas to consider.

What do your environments look like? Anything you would add to this post? Let me know in the comments below!

Happy coding!
Ryan from The Bunch

Use Case: Not on a Campus or in an Office?

coffee_shop

I’ve talked about how useful LunchBunch is in college and in the office, but what about the rest of us?

I organized many meals on campus while attending the University of Delaware and also in work settings during various internships over the past few years. But since graduating in May 2014, I’ve been working on LunchBunch from home which means a lot of meals by myself. So how is LunchBunch useful for those of us who aren’t on a college campus or working in an office? Here are a few of the ways I use LunchBunch that might help you, too.

Trivia

A pizza place in Pittsburgh hosts a trivia night every Tuesday, and one of my friends was the trivia host there for a while. A bunch of us would go most weeks to eat pizza and compete in the trivia, and LunchBunch was a great way to see who was going on a particular night. The time and location were already decided, and seeing everyone’s RSVP helped us to decide if we should go or wait until the next week when more friends could make it. Trivia is a specific use case, but LunchBunch is helpful for planning similar weekly events.

Last-Minute Plans

You just returned home after running errands, and you have some free time. There’s a new restaurant you’ve been wanting to try out, so you hop on LunchBunch to see who wants to join you. You know it’s last-minute, and it’s too much work to message people individually. With LunchBunch, you see who is hungry and available, and in no time, you’re eating at a new place with a friend or two!

Scheduling Plans

Besides giving you the ability to see who’s available right now, LunchBunch can help you to schedule meals in advance. If you schedule lunch or dinner with a group, it’s easy to track who’s going and update the time or location if plans change. Additionally, when you’re getting ready to head out, you can check for hungry buddies who weren’t included in the original invitation so they don’t feel left out.

What are the unique ways that you use LunchBunch? Do you have suggestions for how we could make LunchBunch even better for you? Please let us know in the comments below!

Sincerely,
Ryan from The Bunch