How do I abstract away dependencies in Android library code? - android

Here is my scenario.
I have an android activity in which I want to abstract my I/O dependencies. The dependencies are represented by this interface (edited for brevity and simplicity):
public interface ITimeDataServer {
TimeRecord[] get(int userID);
void save(TimeRecord record);
}
What I want is for my activity to be able to call these interface methods, and leave the implementation to be supplied by the calling code. (Pretty standard, I think).
ITimeDataServer myServer;
int myUserID;
void loadRecords() {
TimeRecord[] records = myServer.get(myUserID);
// etc...
}
My difficulty is, how can I ensure that myServer gets set?
This seems like a common problem, but I can't find a clean solution.
My first thought would be that myServer would be passed in through the constructor, but Android activities aren't really instantiated with constructors.
I've come up with several solutions, but they're all icky in some way:
Icky Solution 1
Create a static method to launch the activity class which takes an ITimeDataServer parameter and stores it in a static variable from which the activity can access it:
private static ITimeDataSource theDataSource;
public static void launch(Activity currentActivity, ITimeDataSource dataSource) {
theDataSource = dataSource;
Intent intent = new Intent(currentActivity, MainActivity.class);
currentActivity.startActivity(intent);
}
This is icky because (a) the data source is static and not actually associated with the instance, and (b) a consumer could initiate the activity by the standard activity API rather than this static method, which will cause NullPointerException.
Icky Solution 2
I can create a Provider class which provides a singleton instance of ITimeDataSource, which needs to be initialized by the calling library before use:
public class TimeDataSourceProvider {
private static ITimeDataSource myDataSource = null;
public void initialize(ITimeDataSource dataSource) {
myDataSource = dataSource;
}
public ITimeDataSource get() {
if (myDataSource == null)
throw new NullPointerException("TimeDataSourceProvider.initialize() must be called before .get() can be used.");
else
return myDataSource;
}
}
This seems a little less icky, but it's still a little icky because the activity's dependency is not obvious, and since there may be many paths to launch it, it's highly possible that some of them would forget to call TimeDataSourceProvider.initialize().
Icky solution 3
As a variation on #2, create a static IODependencyProvider class which must be initialized with ALL dependencies on app startup.
public class IODependencyProvider {
static ITimeDataSource myTimeData;
static IScheduleDataSource myScheduleData; // etc
public static void initialize(ITimeDataSource timeData, IScheduleDataSource scheduleData /* etc */) {
myTimeData = timeData;
myScheduleData = scheduleData;
//etc
}
public static ITimeDataSource getTimeData() {
if (myTimeData == null)
throw new NullPointerException("IODependencyProvider.initialize() must be called before the getX() methods can be used.");
else
return myTimeData;
}
// getScheduleData(), etc
}
This seems superior to #1 and #2 since a failure to initialize would be much harder to sneak by, but it also creates interdependencies among the data types that otherwise need not exist.
...and other icky variations on that theme.
The common themes that make these solutions crappy:
the need to use static fields to pass non-serializable information to an activity
the lack of ability to enforce initialization of those static fields (and subsequent haphazardness)
inability to clearly identify an activity's dependencies (due to reliance on statics)
What's a nooby Android developer to do?

As long as these dependencies implement Parcelable correctly, you should be able to add them to your intent, then unparcel them as ITimeDataServer and get the correct class.

I found a nice solution here, in the least-loved answer.
I define the library activity as abstract and with no default constructor, but a constructor that takes an interface, like so:
public abstract class TimeActivity extends AppCompatActivity {
private ITimeDataSource myTimeDataSource;
public TimeActivity(#NonNull ITimeDataSource dataSource) {
myTimeDataSource = dataSource;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_time);
// do stuff with myTimeDataSource!
}
}
Then, the calling code can create a concrete subclass with its chosen implementation that does have a parameterless constructor. No static members, easy-peasy!
This allows you to abstract and inject all sorts of crazy behaviours! Woooo!
(Note that the concrete subclass activity needs to be manually added to AndroidManifest.xml, like all activities, or the app will crash when it tries to launch.)

Related

Public Methods for all activities

I have a class called myConstants and in it i list all my constants so when i need them I just reference MyConstants.MYCONSTANT. However, i would like to implement something like this for methods. i am repeating a lot of code, for instance, i have a formatCalendarString(Calendar c) method in 3 activities. seems redundant and unecessary. but i cant make them static because i get static calling non-static errors and the only other way i can think is to make a MyConstant object then call public functions off that object, like this...
MyConstants myConstants = new MyConstants();
myConstants.formatCalendarString(Calendar.getInstance());
is there some way i can just call the formatCalendarString() inside MyConstants class without generating an object?
You can use singleton pattern to cache instances. Keeping methods in something like parent activity does not make any sense (as primary role of activity is user interaction).
Example:
public class MyConstants {
private static MyConstants ourInstance;
private MyConstants() {
//private constructor to limit direct instantiation
}
public synchronized static MyConstants getInstance() {
//if null then only create instance
if (ourInstance ==null) {
ourInstance = new MyConstants();
}
//otherwise return cached instance
return ourInstance;
}
}
You just need a private constructor and public static method that would only generate instance if it is null.
Then, call MyConstants.getInstance().whateverMethod(). It will create only single instance.
However when using singleton, please keep memory leaks in mind. Do not pass activity context directly inside singletons.
If you want to have all methods in activities, you can put then in abstract class BaseActivity, which extends Activity, and then make your activities extends BaseActivity. However, if these methods doesn't correspond to something about activity, I suggest some Singleton or Util class
I agree with Pier Giorgio Misley. It's also good to add a private constructor, because you don't obviously want to instantiate an object.
Can't you just use a parent class? That way you can just inherit the methods and manage in one source. Then you don't have to use static functions then.
Edit: Like Tomasz Czura said, just extend the Class.
public class ParentClass {
public void commonMethod(){
}
}
public class OtherClass extends ParentClass{
}
You can use the Static keyword.
Static methods can be referenced from outside without istantiating the new object.
Just create a class:
public class MyClassContainingMethods{
public static String MyStaticMethod(){
return "I am static!";
}
}
Now call it like
String res = MyClassContainingStaticMethods.MyStaticMethod();
Hope this helps
NOTE
You CAN call non-static from static by doing something like this:
public static void First_function(Context context)
{
SMS sms = new SMS();
sms.Second_function(context);
}
public void Second_function(Context context)
{
Toast.makeText(context,"Hello",1).show(); // This i anable to display and cause crash
}
Example taken from here, you will obiouvsly have to fit it into your needs

Mock objects in Android not passed as parameters

I am trying to test a Fragment I've created in Android. I have complete control of the code, so I can change it as I see fit. The issue is that I'm not sure what design pattern I'm missing to make it reasonable.
I am looking for a way to mock objects in Android that are not passed as parameters. This question suggests that anything you might want to mock should be written to be passed as a parameter.
This makes sense for some situations, but I can't figure out how to get it working on Android, where some of this isn't possible. With a Fragment, for example, you're forced to let much of the heavy lifting be done in callback methods. How can I get my mocked objects into the Fragment?
For example, in this ListFragment I need to retrieve an array of things to display to the user. The things I'm displaying need to be retrieved dynamically and added to a custom adapter. It currently looks as follows:
public class MyFragment extends ListFragment {
private List<ListItem> mList;
void setListValues(List<ListItem> values) {
this.mList = values;
}
List<ListItem> getListValues() {
return this.mList;
}
#Override
public void onCreateView(LayoutInflater i, ViewGroup vg, Bundle b) {
// blah blah blah
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
this.setListValues(ListFactory.getListOfDynamicValues());
CustomAdapter adapter = new CustomAdapter(
getActivity(),
R.layout.row_layout,
this.getListValues());
this.setListAdapter(adapter);
}
}
I'm trying to do this using Mockito and Robolectric.
This is the beginning of my robolectric test case:
public class MyFragmentTest {
private MyFragment fragment;
#Before
public void setup() {
ListItem item1 = mock(ListItem.class);
ListItem item2 = mock(ListItem.class);
when(item1.getValue()).thenReturn("known value 1");
when(item2.getValue()).thenReturn("known value 2");
List<ListItem> mockList = new ArrayList<ListItem>();
mockList.add(item1);
mockList.add(item2);
MyFragment real = new MyFragment();
this.fragment = spy(real);
when(this.fragment.getValueList()).thenReturn(mockList);
startFragment();
}
}
This feels so very wrong. This section from the mockito api points out that you shouldn't have to do partial mocks like this very frequently unless you're dealing with legacy code.
Further, I'm not actually able to mock out the CustomAdapter class using this approach.
What is the right way to do this sort of thing? Am I structuring things incorrectly in my Fragment classes? I suppose I might be able to add a bunch of package-private setters, but this still doesn't feel right.
Can someone shed some light on this? I'm happy to do rewrites, I just want to know some good patterns for dealing with the state in my Fragments and how I can make them testable.
I ended up creating my own solution to this. My approach was to add another level of indirection to each my calls that create or set an object.
First, let me point out that I couldn't actually get Mockito to work reliably with Fragment or Activity objects. It was somewhat hit or miss, but especially with trying to create Mockito Spy objects, some lifecycle methods appeared to not be called. I think this is related to gotcha number 2 shown here. Perhaps this is due to the ways that Android uses reflection to recreate and instantiate activities and fragments? Note that I was NOT incorrectly holding onto the reference, as it warns of, but interacting only with the Spy, as indicated.
So, I wasn't able to mock Android objects that required lifecycle methods be invoked by the framework.
My solution was to create to more types of methods in my Activity and Fragment methods. These methods are:
getters (getX()) that return the field named X.
retrievers (retrieveX()) that do some sort of work to get an object.
creators (createMyFragment()) that create objects by calling new. Similar to the retrievers.
Getters have whatever visibility you need. Mine are usually public or private.
Retrievers and creators are package private or protected, allowing you to override them in your test packages but not making them generally available. The idea behind these methods is that you can subclass your regular objects with stub objects and inject in known values during testing. You could also just mock out those methods if Mockito mocks/spies are working for you.
Taken in toto, the test would look something like the following.
Here is the fragment from my original question, modified to use the above approach. This is in the normal project:
package org.myexample.fragments
// imports
public class MyFragment extends ListFragment {
private List<ListItem> mList;
void setListValues(List<ListItem> values) {
this.mList = values;
}
List<ListItem> getListValues() {
return this.mList;
}
#Override
public void onCreateView(LayoutInflater i, ViewGroup vg, Bundle b) {
// blah blah blah
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
this.setListValues(this.retrieveListItems());
CustomAdapter adapter = this.createCustomAdapter();
this.setListAdapter(adapter);
}
List<ListItem> retrieveListItems() {
List<Item> result = ListFactory.getListOfDynamicValues();
return result;
}
CustomAdapter createCustomAdapter() {
CustomAdapter result = new CustomAdapter(
this.getActivity();
R.layout.row_layout,
this.getListValues());
return result;
}
}
When I test this object, I want to be able to control what gets passed around. My first thought was to use a Spy, replacing the return values of retrieveListItems() and createCustomAdapter() with my known values. However, like I said above, I wasn't able to get Mockito spies to behave when working with fragments. (Especially ListFragments--I had mixed success with other types, but don't trust it.) So, we are going to subclass this object. In the test project, I have the following. Note that your method visibility in your real class must allow subclasses to override, so it needs to be package private and in the same package or protected. Note that I am overriding the retriever and creator, returning instead static variables that my tests will set.
package org.myexample.fragments
// imports
public class MyFragmentStub extends MyFragment {
public static List<ListItem> LIST = null;
public static CustomAdapter ADAPTER = null;
/**
* Resets the state for the stub object. This should be called
* in the teardown methods of your test classes using this object.
*/
public static void resetState() {
LIST = null;
ADAPTER = null;
}
#Override
List<ListItem> retrieveListItems() {
return LIST_ITEMS;
}
#Override
CustomAdapter createCustomAdapter() {
return CUSTOM_ADAPTER;
}
}
In the same package in my test project I have the actual test of the fragment. Note that while I'm using Robolectric, this should work with whatever test framework you're using. The #Before annotation becomes less useful, as you need to update your static state for individual tests.
package org.myexample.fragments
// imports
#RunWith(RobolectricTestRunner.class)
public class MyFragmentTest {
public MyFragment fragment;
public Activity activity;
#After
public void after() {
// Very important to reset the state of the object under test,
// as otherwise your tests will affect each other.
MyFragmentStub.resetState();
}
private void setupState(List<ListItem> testList, CustomAdapter adapter) {
// Set the state you want the fragment to use.
MyFragmentStub.LIST = testList;
MyFragmentStub.ADAPTER = adapter;
MyFragmentStub stub = new MyFragmentStub();
// Start and attach the fragment using Robolectric.
// This method doesn't call visible() on the activity, though so
// you'll have to do that yourself.
FragmentTestUtil.startFragment(stub);
Robolectric.ActivityController.of(stub.getActivity()).visible();
this.fragment = stub;
this.activity = stub.getActivity();
}
#Test
public void dummyTestWithKnownValues() {
// This is a test that does nothing other than show you how to use
// the stub.
// Create whatever known values you want to test with.
List<ListItem> list = new ArrayList<ListItem>();
CustomAdapter adapter = mock(CustomAdapter.class);
this.setupState(list, adapter);
// android fest assertions
assertThat(this.fragment).isNotNull();
}
}
This is definitely more verbose than using a mocking framework. However, it works even with Android's life cycle. If I'm testing an Activity, I'll also often include a static boolean BUILD_FRAGMENTS variable. If true, I'll go call through to super in the appropriate methods or return a known fragment as appropriate. In this way I'm able to inject my test objects and play nice with the Android life cycle.

How to inject a dependency when testing an Android activity without a third-party framework?

I want to test an Android activity CommentActivity that normally constructs and uses an instance of CommentsDataSource (both are classes that I wrote).
public class CommentActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
:
CommentsDataSource = new CommentsDataSource(..);
:
}
:
}
I'm willing to create MockCommentsDataSource myself and would like to avoid using a third-party mocking framework. (Why? Because I'm a teaching trying to reduce the amount of information I need to cram into the semester and the amount of software my students need to install. I've seen other posts that recommend Guice, roboguice, and Spring.)
My question is how to pass a CommentsDataSource (or MockCommentsDataSource) to the Activity. It doesn't seem practical to make them Serializable or Parcelable, which they would have to be in order to be passed in through the Intent that starts CommentActivity. While I could easily pass in a debug flag, using it would require CommentActivity to know about MockCommentsDataSource, which is really none of its business (and in a separate application):
public class CommentActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
:
debugMode = getIntent().getBooleanExtra(DEBUG_MODE, false);
// Get a connection to the database.
final CommentsDataSource cds = (debugMode ?
new MockCommentsDataSource() : // Abstraction violation
new CommentsDataSource(this));
:
}
:
}
How should I inject MockCommentsDataSource into CommentActivity? FWIW, I'm using Eclipse and am developing for recent SDK versions.
One solution that occurs to me is to use the abstract factory pattern, since it would be relatively easy to make the factories serializable. Is that the best approach, given my constraints?
Here are two ideas:
Not using factory:
This will probably work only for unit tests and not for integration tests:
Create a method that returns CommentsDataSource, e.g. getCommentsDataSource()
Create a class that inherits CommentActivity
Override the getCommentsDataSource() with a method that returns MockCommentsDataSource
Test the new class
Using factory:
As you mentioned, you can change the CommentActivity code to get the CommentsDataSource from a factory method. this way you can have the mock class returned by the factory method.
Hope this helps!
I have a simple and ugly solution to offer, using a private static field to inject the dependency:
private static Client client;
and set the field value from the test using reflection:
public static void setStaticFieldValue(final Class<?> clazz,
final String name, final Object value) throws Exception {
final Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
field.set(null, value);
}
then, in i.e. onCreate(), use that "injected" test instance if the field is set and use the regular one otherwise.
Ugly, but requires only few changes relevant to testing to the class under test.

What version of RoboGuice works with Android SDK 8?

That's probably part one of my question.
Basically I'm struggling with the actual injection for version 1.1.2. I've read the couple of pages on the site, and I feel I'm missing something.
Basically I've done the RoboApplication extension. I've overridden the addApplicationModules method. I've even made a module.
My module looks like this:
public class DataRepository extends AbstractAndroidModule
{
#Override
protected void configure() {
/*
* This tells Guice that whenever it sees a dependency on a TransactionLog,
* it should satisfy the dependency using a DatabaseTransactionLog.
*/
bind(IDataBaseAdapter.class).to(DataBaseAdapter.class);
}
}
In my adapter I have this:
public class DataBaseAdapter implements IDataBaseAdapter
{
private DataBaseHelper _dbHelper;
private SQLiteDatabase _db;
#Inject
protected static Provider<Context> contextProvider;
public DataBaseAdapter()
{
_dbHelper = new DataBaseHelper(contextProvider.get());
}
}
If I don't do there, where is the opportune place for the chunk of code to reside... where I associate injectors?
Finally... my Application has an injection of it like so:
public class MyApplication extends RoboApplication
{
public MyApplication()
{
super();
}
public MyApplication(Context context)
{
super();
attachBaseContext(context);
}
#Override
protected void addApplicationModules(List<Module> modules)
{
modules.add(new DataRepository());
}
#Inject
private IDataBaseAdapter adapter;
public IDataBaseAdapter getAdapter()
{
return adapter;
}
public void setAdapter(IDataBaseAdapter value)
{
adapter = value;
}
...
}
I'm trying to use the Inject attribute as shown. For example:
#Inject
private IDataProvider provider;
A couple of reasons why I'm lost is that I come from a .NET and Flash/ActionScript background plus I've only used StructureMap instead of Ninject (in the .NET world), which I've heard Guice is designed with some of the ideas of Ninject in mind. Could someone help me figure out this small piece?
I'd really like to focus on using 1.1.2 instead of jumping to 2.x of RoboGuice... especially since it is still in beta, so I hope you all don't mind.
Thanks again,
Kelly
Android is quite different from standalone / hosted java application. You do not have main() , but you have certain activity units, which are managed by android framework (activities, services , broadcast receivers)
DI is a technique which allows you to eliminate booler plate code by wiring together
parts in good object oriented way.
As your unit of work is mostly activity, you shall do wiring / creation of your collaborating objects in onCreate() method , and there are dedicated onResume() and onPause() methods (see actviity lifecycle)
Rule of thumb is, does this thing needs to be restarted every time activity loses it focus? If yes, initialize / destroy it in inResume() / onPause(), otherwise - in onCreate()
And if you like to share objects withing entire application ( running in same JVM ) , it is OK to use singleton pattern in android. So you may just have singleton injector factory , and cosult it from everywhere:
InjectorFactory.getInstance(<context if necessary?>).getInstance(whatever you need);
OK, I've figured out what was needed, but I'm not quite sure why after seeing all the information floating out there.
I basically made this change, and now my test passes.
public class DataBaseAdapter implements IDataBaseAdapter
{
private DataBaseHelper _dbHelper;
private SQLiteDatabase _db;
#Inject
public DataBaseAdapter(Provider<Context> contextProvider)
{
_dbHelper = new DataBaseHelper(contextProvider.get());
}
}
While I like using constructors as the tool for injecting, I wonder why it had to work this way, considering that examples I have seen are some kind of reflection class injection.
Anyway, that's this part. Hopefully someone else will find this useful.
Cheers,
Kelly

Is there any convention for a helper class in Android?

For every Activity I add to my app I'm noticing a lot of similar code being used in the initialization of the Activity. A helper class with a static method to wrap this similar code seems the way to go.
I first thought of a singleton class. I could add static methods/variables and use them across the application. I haven't really tried to see how would this work in an Android application. Searching a little bit more I saw something about creating a class extending Application. For this I did a simple test:
public class MyApp extends Application {
public static String DEMOTEXT = "WORKING!";
public static void ShowToast(Context context, String text) {
Toast.makeText(context, text, Toast.LENGTH_SHORT).show();
}
}
MyApp.ShowToast(this, MyApp.DEMOTEXT); // Placed on onCreate of some Activity
This works exactly as I expected. Is this the way to go on Android or is there a better convention? Anything else I should consider when doing this?
By the way, should I use the final keyword on the string? What about the method?
EDIT: I just read this:
There is normally no need to subclass Application. In most situation,
static singletons can provide the same functionality in a more modular
way. If your singleton needs a global context (for example to register
broadcast receivers), the function to retrieve it can be given a
Context which internally uses Context.getApplicationContext() when
first constructing the singleton.
http://developer.android.com/reference/android/app/Application.html
Should I use a singleton then?
Application is primarily used for a global application initialization. You would create your own class, override Application.onCreate() and initialize your static application data there.
Dont forget to declare it in the AndroidMainfest.xml:
<application
android:icon="#drawable/icon"
android:label="#string/app_name"
android:name="your.package.path.to.MyApp">
A static helper class is made the way you did.
The convention is to use lower case letter at first position, so MyApp.showToast(...).
You would use final for the String if you would want to avoid madifications on other places (since it should be a contant).
// this would allow ...
public static String DEMOTEXT = "WORKING!";
// ... to do this somewhere else
MyApp.DEMOTEXT = "NOT WORKING!"
I haven't tried this but I think you should be able to do something like this as well.
public class MyActivity extends Activity {
private static final String DEMOTEXT = "WORKING!";
#Override
public void onCreate(Bundle bundle)
{
super.onCreate(bundle);
Toast.makeText(this, DEMOTEXT, Toast.LENGTH_SHORT).show();
}
}
Now for all activities that need to use that initialization could just extend your base activity class.
public class SomeActivity extends MyActivity {
...
// Should display the toast on create
...
}
Yes just use a singleton. Well in this case if your methods are static, you don't even need a singleton. Just a class with static methods.

Categories

Resources