March 2011 - Posts

Android: Encapsulating Shared Preferences

The Android OS gives you a convenient way to save and load simple data (i.e. string, float, int, boolean and long) in the form of SharedPreferences.  The data is stored in a dictionary format that utilizes a key/value pair.  The “name” of the preferences is also supplied by your code.  In a lot of the samples you’ll find online, the name of the shared preferences and all of the keys are stored as constants at the top of the Activity class (or worse, the key names are copy/pasted throughout the code!).  I don’t like polluting my Activity classes with stuff like that so I’ve been encapsulating my preferences in their own class.

Here’s a simple preferences class that exposes a couple of pieces of data – Full name and Age:

package com.example;
 
import android.content.Context;
import android.content.SharedPreferences;
 
public class AppPrefs
{
    private final static String ACCOUNT_PREFS_NAME = "prefs";
    private final static String FULLNAME_KEYNAME = "FULLNAME_KEY";
    private final static String AGE_KEYNAME = "AGE_KEY";
 
    private final Context context;
    private String fullName;
    private int age;
 
    public AppPrefs(Context ctx)
    {
        this.context = ctx;
        SharedPreferences prefs = context.getSharedPreferences(ACCOUNT_PREFS_NAME, Context.MODE_PRIVATE);
        fullName = prefs.getString(FULLNAME_KEYNAME, "unknown");
        age = prefs.getInt(AGE_KEYNAME, 18);
    }
 
    public String getFullName()
    {
        return fullName;
    }
 
    public void setFullName(String name)
    {
        fullName = name;
    }
 
    public int getAge()
    {
        return age;
    }
 
    public void setAge(int number)
    {
        age = number;
    }
 
    public void Save()
    {
        SharedPreferences prefs = context.getSharedPreferences(ACCOUNT_PREFS_NAME, Context.MODE_PRIVATE);
        SharedPreferences.Editor edit = prefs.edit();
        edit.putString(FULLNAME_KEYNAME, fullName);
        edit.putInt(AGE_KEYNAME, age);
        edit.commit();
    }
}

You can see it’s a very simple class, but it hides all the key names within the class.  The main consumer of this class doesn’t need to know the name of the keys or even how the data is stored.  By simply using the get/set methods and the Save() method, the Activity can concentrate on what it was designed to do.  Imagine if we need to change where we’re storing the data?  Maybe we’re moving from SharedPreferences to a SQLite database?  In that case, we simply change the preferences class and the Activity won’t need any modifications.

I haven’t done a lot of Android programming yet, but so far, this technique has been working out well.  I’ve created a sample application based on IntelliJ IDEA 10 using this technique on my bitbucket account.

Technorati Tags: ,
Posted by PSteele | with no comments
Filed under: ,

.hgignore file for IntelliJ IDEA Development

Every time I start a new project in Visual Studio, I almost always put it under Mercurial source control – even a small demo project.  If the project becomes serious enough, I’ll create a private repository in Bitbucket and maintain it there.  After I initialize my Mercurial repository, the first thing I do is grab Nino’s .hgignore file for Visual Studio.  It’s a great time-saver.

I’ve been playing around with Android development a bit lately using JetBrains IntelliJ IDEA 10.  Like my Visual Studio projects, I also create a local Mercurial repository for my Android code.  But since I’m new to Android development, there were a bunch of files (other than the source code I was writing!) and I didn’t know if these should be stored in my source code control system or not.

Luckily, JetBrains has a KB article on the subject: How to manage IDEA projects under Version Control Systems.  Using this info, I’ve created a stock .hgignore file I use for all of my Android projects.  Here’s the contents:

glob:.idea/workspace.xml
glob:.idea/tasks.xml
glob:out/*

I hope this useful for you.  If you know of any changes I could make, let me know!

Technorati Tags: ,,

Posted by PSteele | with no comments
Filed under: , ,

Automapper: Handling NULL members

A question about null members came up on the Automapper mailing list.  While the problem wasn’t with Automapper, investigating the issue led to an interesting feature in Automapper.

Normally, Automapper ignores null members.  After all, what is there really to do?  Imagine these source classes:

public class Source
{
    public int Data { get; set; }
    public Address Address { get; set; }
}
 
public class Destination
{
    public string Data { get; set; }
    public Address Address { get; set; }
}
 
public class Address
{
    public string AddressType { get; set; }
    public string Location { get; set; }
}

And imagine a simple mapping example with these classes:

Mapper.CreateMap<Source, Destination>();
 
var source = new Source
                {
                    Data = 22,
                    Address = new Address
                                {
                                    AddressType = "Home",
                                    Location = "Michigan",
                                },
                };
 
var dest = Mapper.Map<Source, Destination>(source);

The variable ‘dest’ would have a complete mapping of the Data member and the Address member.

But what if the source had no address?

Mapper.CreateMap<Source, Destination>();
 
var source = new Source
{
    Data = 22,
};
 
var dest = Mapper.Map<Source, Destination>(source);

In that case, Automapper would just leave the Destination.Address member null as well.  But what if we always wanted an Address defined – even if it’s just got some default data?  Use the “NullSubstitute” option:

Mapper.CreateMap<Source, Destination>()
    .ForMember(d => d.Address, o => o.NullSubstitute(new Address
                                                         {
                                                             AddressType = "Unknown",
                                                             Location = "Unknown",
                                                         }));
 
var source = new Source
{
    Data = 22,
};
 
var dest = Mapper.Map<Source, Destination>(source);

Now, the ‘dest’ variable will have an Address defined with a type and location of “Unknown”.  Very handy!

Technorati Tags: ,,
Posted by PSteele | 1 comment(s)
Filed under: ,
More Posts