A simple task such as displaying your gallery photos in a ListView component can lead to a significant loss of performance in your Android application, to the point where it would render the application
unusable. Worse yet, the application might run out of memory and crash while loading bitmaps. Just think about user quickly scrolling through a list of hundreds of photos each the size of 3-10 megabytes.
Thus, to display pictures in ListView is not straightforward and requires several performance considerations.
It doesn’t make sense for us to keep default ListView behavior which continuously frees up and loads our bitmaps when our users scroll back and forth through the list.
Caching allows us to store bitmaps in memory and quickly retrieve them on consecutive views while scrolling. Thankfully, Android provides us with
LRUCache that helps us cache our bitmaps. Thus, we can create a fairly simple class for our LRUCache.
The above code allows creation of LruCache with a quarter of available memory, and adding and retrieving bitmaps by key value, which is a position of an image in our ListView.
Loading hundreds of full-sized image bitmaps would quickly cause our application to crash from lack of memory. Oftentimes, displaying image at fraction of the original size in a list is sufficient.
The functions below help us resize the image and resample the bitmap before using it further.
Basically, calculateInSampleSize takes original image width or height and divides them by the target width or height. Returned inSampleSize then gives us a divisor to create processed bitmaps that are a
fraction of the original size. Finally, decodeSampledBitmapFromString reads our bitmap from provided image path and returns resized smaller bitmap.
Initially, we want to load all our bitmaps in a separate thread or process, so we do not freeze our UI thread. To achieve that, we can use
AsyncTask. In our case, this is also where we want to re-sample our bitmaps and place the images into cache. Therefore,
our AsyncTask would look like this:
Putting it all together
In the main activity, we would initialize our bitmap cache in onCreate() method:
Then, in our ListView adapter, we would add loadBitmap() function to either set ImageViews bitmaps from cache or to start a new AsyncTask.
Also, we could also do other things to optimize performance, such as implementing ViewHolder Pattern to recycle views
in a static class. In our example, ViewHolder will hold two things: ImageView and its position in ListView.
Finally, Android has a limit of 128 simultaneous AsyncTasks and gives an error if we exceed that limit. This error is entirely possible when loading a thousand bitmaps in a ListView.
One way to prevent the error from happening and to manage memory is to implement a static class to keep and control current AsyncTask count.
Our AsyncTask class could then increment the count in the AsyncTask constructor and decrement in onPostExecute() method. We would check the current count against arbitrary maximum
prior to launching new ImageLoaderTask(...) in List Adapter loadBitmap(...) method.
Marginalized women in Vancouver need a portable health record that can empower and support them through their pregnancies. Many of these women have chaotic lives and face multiple challenges that would
make a paper-based pregnancy passport difficult to retain. Despite these women’s financial situations, most have an Android smartphone.
Thrive Pregnancy is an Android application that empowers women to make positive choices for their pregnancy. The project was initiated at Hacking Health Vancouver 2014
conference by two doctors from Youth Pregnancy and Parenting and Sheway Programs. Thrive Pregnancy application enables vulnerable pregnant women to access important pre-natal information
and local support resources, record text-, voice-, and picture-based diary entries, appointments and test results, and keep track of needs and questions to discuss with their care providers.
After joining doctors and project team at the conference, we decided to complete the Android application pro bono over the next two months.
During the project, I led a team of five people in a project management role and significantly contributed to Android development.
Thrive Pregnancy smartphone app includes:
Information for women to think about and discuss with their care provider relating to their prenatal care choices;
Information for women to think about their needs for their pregnancy;
Information about the care women can expect during pregnancy;
A place to keep notes and a record of appointments, tests and results;
Oftentimes, such as when hacking demos, we want our client side app talking to some form backend without spending too much time on it. One way to do it in a Microsoft environment is to do a quick
POST request using HTTPWebRequest object. HTTPWebRequest does exactly what the name suggests and saves us a lot of time from having to write our own HTTP calls.
As simple as URL
During the first step, we would split our URL such as http://www.someserver.com/service.aspx?var1=val1.. into the address
of the server and the body containing our POST variables. Of course, if we were creating a GET request, then we would not need to do that.
Next, we would create HTTPWebRequest object using the above uri in the constructor and assign whichever HTTP header variables we need.
Since we are POSTing to some form backend, we would also need to tell the server that we are submitting a form:
And finally, since we are sending a POST request, our URL GET variables will go into the body of our HTTP request.
The whole HTTP request
P.S. And what about the response?
To obtain the response from the server, we would simply use HTTPWebResponse object and use StreamReader to get the body of the response.
Sometimes, we may want to have our own MIMEs (as in Mail Extensions messages, although bossing around an entourage of stripy shirt artists may be fun) for use
with such programs as sendmail. While creating a simple text email using MIME is simple, adding attachments requires a bit of work and can be tricky. Thankfully, Linux Bash Shell gives us the
right tools to get the job done.
In this example, let’s say we want to add a .jpg file as an attachment to our MIME message.
Step 1 - Specify attachment
We are using the file called test.jpg as an attachment.
Step 2 - Determine MIME type
Now, we need to determine what MIME file type we are dealing with. One command we can use is gnomevfs-info which gives us the relevant file information. At the same time, we can use pattern-matching
command such as awk to find the specific information we are looking for.
Step 3 - Encode attachment
MIME requires us to encode the attachment in base-64. We can use uuencode command to do that. After the encoding, we would need to remove first and last lines, which specify start and end of encoding.
sed stream editor will help us easily remove those lines.
At this point, we created attach.temp file containing our base-64 encoded jpg attachment. $attachdata variable contains text output of this file.
Step 4 - Create email boundary
A multi-part MIME message require boundaries between different parts of the message, and at the start and end of the message body. Boundary could be anything specified by boundary argument in Content-Type
MIME header. In our case, we will use the first 32 characters of MD5 checksum of current time in seconds as a message boundary, using md5sum command.
Step 5 - Create email message
Finally, we can create our MIME message.mail file and combine it with our boundary and attachment.
For a more complete example which uses cron to schedule sendmail to send MIME messages, please check out my github repository.