Android Developer

Los Angeles Freelance Developer

Android Developer header image 2

Android Architecture: Part 10, The Activity Revisited

July 9th, 2012 · 44 Comments · Android, OOP

Back in Part 4 of the series I mentioned that the Activity naturally functions like a controller and not a View. If you examine the hook methods (like onPause, onResume, etc) and how the Activity is created it becomes clear that the Activity isn’t a View. Views should be dumb. Controllers are smart and handle logic. These hooks are all logical points of execution and not related to View behavior. Since writing that post, all my projects have used the approach I outline here. It’s very solid architecture and it doesn’t leave me feeling unsettled like the approach from Part 4. It provides clear separation of MVC parts without the overlap.

Hopefully you’ve read through the previous parts in the series because we’re going to be building off those ideas and making some slight adjustments.

  1. The Activity will function as a controller.
  2. The View will subclass either RelativeLayout, LinearLayout, FrameLayout, etc….
  3. Handlers are not used for passing Events between the parts. We’ll use an EventDispatcher from the Model and simple OnSomethingListeners from the View.

That’s it. It’s really just a couple of simple changes. So let’s get started with the specifics. The example is a timer and you can get the full sources here. (I’m going to leave out a lot of the details that are not in the scope of this post. Feel free to check out the other stuff on your own. There’s some cool stuff in there.)

Our simple example only has 1 activity called MainActivity:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
public class MainActivity extends Activity {
 
	private AppModel model;
	private MainView view;
	private Handler handler;
	private boolean isTimerRunning = true;
	private long initTime = 0;
 
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		initTime = System.currentTimeMillis();
		model = AppModel.getInstance();
		view = (MainView)View.inflate(this, R.layout.main, null);
		view.setViewListener(viewListener);
		setContentView(view);
		handler = new Handler();
	}
 
	@Override
	protected void onResume() {
		super.onResume();
		timerRun.run();
	}
 
	@Override
	protected void onPause() {
		super.onPause();
		handler.removeCallbacks(timerRun);
	}
 
	@Override
	protected void onDestroy() {
		super.onDestroy();
		view.destroy();
	}
 
	/**
	 * Simple runnable to update our current time in the  model
	 */
	private Runnable timerRun = new Runnable() {
		@Override
		public void run() {
			if (isTimerRunning) {
				long change = System.currentTimeMillis() - initTime;
				initTime = System.currentTimeMillis();
				model.setElapsedTime(model.getElapsedTime() + change); // controller is responsible for updating the model
				handler.postDelayed(timerRun, 100);
			}
		}
	};
 
	/**
	 * This is how we receive events from the view.
	 * The view takes user actions
	 * The controller/activity responds to user actions
	 */
	private MainView.ViewListener viewListener = new MainView.ViewListener() {
		@Override
		public void onToggleTimer() {
			isTimerRunning = !isTimerRunning;
			view.setPausedState(isTimerRunning); // controller can call method directly on the view
			if (isTimerRunning) timerRun.run();
		}
 
		@Override
		public void onAddTime(long amountToAdd) {
			model.setElapsedTime(model.getElapsedTime() + amountToAdd);
		}
	};
}

This should all look very familiar. There are only 3 important things I want to point out here:

  1. On line 14 is where we are creating the View. In this instance I inflate a resource xml layout file. Notice it’s casted to a custom object.
  2. Lines 15 and 58 are how the View sends events to the Controller. This should be super familiar because this is how we listen to button events and other standard Android events. In our case we’re listening for custom events from our View.
  3. The controller is allowed to make direct method calls on the View. On line 62 you can see the state of the Stop/Start button is set.

And that’s all the changes for the Activity to be the Controller. The rest of this class just keeps track of a timer and like a good controller,  updates the model property. Let’s check out the View.

You’re probably very familiar with creating “views” in xml, but did you know they can be linked to a class? Here’s what main.xml looks like and why in the controller I was able to type cast it to “MainView”:

<com.musselwhizzle.mvc.views.MainView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    >

The layout file points to MainView. Let’s check out that code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
public class MainView extends LinearLayout {
 
	/**
	 * The interface to send events from the view to the controller
	 */
	public static interface ViewListener {
		public void onToggleTimer();
		public void onAddTime(long amountToAdd);
	}
 
	private static boolean DEBUG = false;
	private static final String TAG = MainView.class.getSimpleName();
	private static final long AMOUNT_TO_ADD = 1234 * 60 * 2;
	private Digit d1, d2, d3, d4, d5;
	private Button toggleBtn, addBtn;
	private AppModel model;
 
	/**
	 * The listener reference for sending events
	 */
	private ViewListener viewListener;
	public void setViewListener(ViewListener viewListener) {
		this.viewListener = viewListener;
	}
 
	/**
	 * Constructor for xml layouts
	 */
	public MainView(Context context, AttributeSet attrs) {
		super(context, attrs);
		model = AppModel.getInstance();
	}
 
	/**
	 * Exposed method so the controller can set the button state.
	 */
	public void setPausedState(boolean isTimerRunning) {
		String txt = (isTimerRunning) ? getContext().getString(R.string.stop) : getContext().getString(R.string.start);
		toggleBtn.setText(txt);
	}
 
	/**
	 * Remove the listener from the model
	 */
	public void destroy() {
		model.removeListener(AppModel.ChangeEvent.ELAPSED_TIME_CHANGED, elapsedTimeListener);
	}
 
	/**
	 * Does the work to update the view when the model changes.
	 */
	private void bind() {
		int milli = (int)Math.floor((model.getElapsedTime() % 1000));
		int secs = (int)Math.floor((model.getElapsedTime() / 1000) % 60);
		int mins = (int)Math.floor((model.getElapsedTime() / 1000 / 60) % 60);
 
		if (DEBUG) {
			Log.i(TAG, "elapsed: " + model.getElapsedTime());
			Log.i(TAG, "secs: " + secs);
			Log.i(TAG, "mins: " + mins);
		}
 
		d1.showTime((int)Math.floor(mins/10));
		d2.showTime(mins % 10);
		d3.showTime((int)Math.floor(secs/10));
		d4.showTime(secs % 10);
		d5.showTime((int)Math.floor(milli/100));
	}
 
	/**
	 * Find our references to the objects in the xml layout
	 */
	@Override
	protected void onFinishInflate() {
		super.onFinishInflate();
		toggleBtn = (Button)findViewById(R.id.toggleBtn);
		addBtn = (Button)findViewById(R.id.addTimeBtn);
		d1 = (Digit)findViewById(R.id.digit1);
		d2 = (Digit)findViewById(R.id.digit2);
		d3 = (Digit)findViewById(R.id.digit3);
		d4 = (Digit)findViewById(R.id.digit4);
		d5 = (Digit)findViewById(R.id.digit5);
		DigitObjectPool pool = new DigitObjectPool(getContext(), 10);
		d1.setPool(pool);
		d2.setPool(pool);
		d3.setPool(pool);
		d4.setPool(pool);
		d5.setPool(pool);
 
		toggleBtn.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				viewListener.onToggleTimer();
			}
		});
		addBtn.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				viewListener.onAddTime(AMOUNT_TO_ADD);
			}
		});
		model.addListener(AppModel.ChangeEvent.ELAPSED_TIME_CHANGED, elapsedTimeListener);
		bind();
	}
 
	/**
	 * The listener for when the elapsed time property changes on the model
	 */
	private EventListener elapsedTimeListener = new EventListener() {
		@Override
		public void onEvent(Event event) {
			bind();
		}
	};
}

So again there are only a couple of important things (as related to MVC) going on here.

  1. The view is binding to the elapsed time on the model although this isn’t new.
  2. Instead of using a Handler to send events we’re just using a standard listener as defined on lines 5 and 21.

Everything else that happens in this class is just View-related stuff to make it pretty. Notice in this case MainView subclasses LinearLayout and gets all the references to the components in the onFinishInflate() method. Alternatively, you don’t have to use an xml resource file and could just create the layout in code in the constructor.

So that’s it! It’s just a couple of simple changes, but it works much better than having the Activity function as a View. A lot of you guys have been asking for this update. I hope this helps and clears up the idea. Happy coding!

Get the sources from here.

Tags: ·······

44 responses so far ↓

  • 1 Android Architecture: Part 4, The View - Android Developer // Jul 9, 2012 at 2:27 pm

    [...] UPDATE #2: Thanks for all the questions, comments, and feedback guys. I’ve finally gotten around to making a blog post about the Activity as a Controller. It’s over here if you want to check it out. [...]

  • 2 Deepak // Jul 17, 2012 at 7:13 am

    Thank you ! Your codes teach a lot more than I wish for :)

  • 3 Antoine Grondin // Jul 21, 2012 at 3:53 am

    Thanks for the update! I’m a student and your series introduced me to a clear, understandable example of MVC (I didn’t cover that yet in my curriculum, but needed some architecture knowledge for my personal projects), and your series made just that. I was waiting for this update, as I am since going thru great loops to make the Activity works has Views .

    The way I made it so far is to put the Controller in a Service that invoke the Activities, but I feel it is perfectible. Now your new post clarify much, I really appreciate it!

  • 4 Tal Weiss // Jul 25, 2012 at 4:44 am

    Thank you for the great post – again!

    If I could add to the wish-list of future posts, I would love to see an expanded example with web services (how exactly do they fit in), Fragments (controllers?) and testing (maybe even TDD?).

    Thanks again!

  • 5 Fernando Gutiérrez // Jul 30, 2012 at 5:50 pm

    Thanks for the article, I was looking forward to it.

    I’d also like to know your opinion about what role fragments should play in a MVC architecture.

  • 6 musselwhizzle // Jul 30, 2012 at 6:07 pm

    Hi Fernando, Thanks for the comments. I (often) use fragments as controllers.

  • 7 cameo // Sep 24, 2012 at 6:55 am

    Hi musselwhizzle,
    Thanks for the practical blog series again! I can learn a lot from it. I am looking forward to your opinion on MVP. here is a reference(http://magenic.com/Blog/AnMVPPatternforAndroid.aspx).

    BTW, i suggest you to put your code to Github.

  • 8 cameo // Sep 24, 2012 at 6:59 am

    I think fragment is quite flexible. It can be used as view and controller depending on the context. I am interested in how fragments communicate with the hosting activity via listeners.

  • 9 Jack Le // Nov 22, 2012 at 9:46 am

    Thanks again for so helpfull article serie. This serie teach me alot of things. So now, Im trying to apply this model to my app. So I have some questions and I hope that you can give me some advices or solutions.

    When you using this model, did you have some interfaces for view, and controllers. Did you using a base controller like BaseActivity for all activities and if you have what you do with it?

    Can one controller has many models and a view can contain other views.

    Thanks for reading my comments and sorry for my terrible enlgish.

    Best regards,
    Jack Le

  • 10 musselwhizzle // Nov 23, 2012 at 2:38 pm

    Hi Jack, You’re welcome. To answer your questions

    1) Do I use interfaces for views & controllers? Most of the time no. I only use interfaces when it’s needed and a lot of times that isn’t on a view.

    2) Do I use a BaseActivity for all my activities and if you have what you do with it? Absolutely! Stuff that goes in there are things like analytics, dialogs, common convenience methods, and common onSave stuff.

    3) Can one controller have many models? Yes. Let’s say you have a user model which is used to populate other specific list data to your app (Youtube’s navigation and content for instance). You can have as many model as you need. If you extend the definition of model a little bit there are things like VOs (Value Objects) and POJOs (Plain Old Java Objects). These objects just hold values or properties (or state). In a typical app I might have 15-30 of them.

    4) Can a view can contain other views? Sure. You may or may not decide to expose that your view contains subviews. That’s up to you. The Principle of Least Knowledge might suggest not exposing it but it depends. It might not be so bad if you did for views.

    Hope that helps!
    Cheers
    josh

  • 11 Jack Le // Nov 24, 2012 at 9:18 am

    Dear Josh
    Thanks for clearly answer.
    You have helped me alot.
    Thank you so much.
    jack,

  • 12 Tim Kurtz // Jan 4, 2013 at 9:43 pm

    I really learned a lot from your posts on this. I come from the VB world and am trying to migrate to Android.

    I’m working on a project which uses an SQLite database to track projects. In this architecture I have one model for Projects and three views:
    * Project List
    * Project Edit/Add (click the list or menu option to edit or add a record)
    * Project Show (click the list to display the project record)

    I get the impression that I should have one activity that controls all three views… or should I have one activity for each view?

    If I add another model, ProjectVisits with similar views for the visits. Should I:
    * have another activity that controls those three views
    * have a separate activity for each view
    * have one activity that controls every view – Project and ProjectVisits

  • 13 musselwhizzle // Jan 4, 2013 at 11:52 pm

    Hi Tim, Generally you have 1 activity per 1 UI screen. I would base the decision upon that. Alternatively, you could do 1 activity and 3 fragments that switch in and out. You would see something like this in combination with the PullMenu/PullSlider menu pattern that’s emerging.

  • 14 Tim Kurtz // Jan 5, 2013 at 12:42 am

    That makes sense to me. The earlier post with the different list classes confused me the listcontroller and listadapter and no listactivity.

    Is there a reason the earlier example had an app class at the root of the package and this one doesn’t? Is it not needed with only one activity? What’s it’s purpose? I’m thinking it has something to do with clumping activities together like I’m going to be doing and getting an instance of the application which this example didn’t need since it was only one activity.

    I really appreciate your blog and comments on this and how fast you responded.

    Tim

  • 15 musselwhizzle // Jan 5, 2013 at 1:05 am

    The “app” class you’re referring to a subclass of “Application.” It can be used for general setup.

  • 16 Stephen // Jan 20, 2013 at 12:52 am

    Great post… it’s really interesting to see MVC applied to Android. I was hoping you could do another post at some point demonstrating the following:

    - How web-service calls are integrated into the MVC pattern.

    - How exactly you propagate model change events to multiple views in your application.

    - Tied to the above, how you store the model data that is shared by multiple views/activities. Do you store it centrally somewhere?

    Thanks :)

  • 17 Tim Kurtz // Jan 29, 2013 at 10:27 pm

    This has been a really great series of articles. If I understand this right…I have a database of projects and I want the app to list them, show a particular project the user selected and add a project so based on the Single Responsibility Principle I need a ProjectListActivity, ProjectShowActivity and ProjectAddActivity. ProjectListActivity and associated view classes. And each …Activity will handle calls to the other two as needed and each will handle their menu items. And I don’t need an overall Project Controller activity that calls the others as needed? Is that correct?

  • 18 Tim Kurtz // Jan 29, 2013 at 10:31 pm

    Followup, actually ProjectListActivity will redirect to the other two as needed and when one of them are done control will revert to ProjectListActivity?

    I come from years of VB programming so this is fairly new to me. I understand the MVC concept it’s the implementation that confuses me sometimes.

  • 19 musselwhizzle // Feb 2, 2013 at 1:20 am

    Yup. Sounds like you got the right idea to me. Good luck!

  • 20 Randy // Feb 2, 2013 at 10:22 pm

    Thanks for the tutorial. Its been been very helpful.. I like your previous design better for my application. What I don’t like about the new version is the dynamically creating the activities. However, I fairly new to Android developer. But, I have seen large corporation Android code and the initial version makes sense. I know it does not fit nicely into the MVC box, but seems easier to understand and support. What are your thoughts?

  • 21 Luciane // Feb 19, 2013 at 12:57 pm

    Hi,

    Love your blog and learned a lot here. I have a questions about cursors. I’m developing a app for a tablet and trying to apply mvc following your steps. I have a couple ListActivitys that have ListViews with CursorAdapters. How would you deal with cursors and where would they come in the MVC architecture? Should I avoid using them at all? When I look at it, they should be restricted to the persistance layer but, the ListView is heavily coupled with it. So… Any light on the matter?

    Thank you very much… I already have your blog on my RSS reader. :)

  • 22 musselwhizzle // Feb 20, 2013 at 12:33 am

    Hi Luciane, “they should be restricted to the persistance layer but, the ListView is heavily coupled with it”. Yea this is why I don’t use CursorAdapters too often. I instead just parse my data from the DB, Contacts, data provider, whatever, myself in my business layer and create Value Objects. It decouples the Adapter from having to know about the internals of how the data was stored. Would I recommend avoiding CursorAdatpers? No, I think I’d be executed by the Android community if I said that. They certainly have their use. The good news is ListView to Adatper is very decoupled. Any kind of coupling should happen at the concrete instance of the Adapter: MyCursorAdapter, MyArrayAdapter, MyBaseAdapter, etc… These are all polymorphic types but the internals are very concrete (this is okay and good) but the client never sees this. In terms of getting the adapter to the view, sometimes I have my controller activity/fragment aggregate (pass) the Adapter into the View and sometimes I’ll have the View compose (create) it’s own Adapter based upon the data in the model. I hope that helps. Thanks for the comment. Good luck on your project!

  • 23 William // Feb 23, 2013 at 1:41 am

    Hi, excellent posts! Read all of them, passed them on to my friends and i’ve been using what i learned here to guide me through my recent projects.

    With a specifc one i found myself with a few doubts.

    I have an Activity that must be the controller for a ListView that has a list with 2 different types of value, each one with a different layout. The itens to be displayed on the list come from my Model.

    Following the sequence that you’ve shown here, my Activity retrieves the Model from the DAO, initializes and inflates my View and registers a ListViewListener on the View.

    Now, after the View was inflated and all the View’s controls were found and had their events set to point to the ListViewListener, how should i get the View to access the same Model instance from the Activity and its values without having a Singleton model?

    I need this Model on the view, so it can be passed to my CustomListViewAdapter (that needs the model’s values to do the 2 different layout thing) and also to register my View as a Listener to the model.

    Sorry for the giant post and if i asked any stupid questions here. I’m new to the MVC on Android.

    Thanks for the great posts and for all the help!

  • 24 musselwhizzle // Mar 4, 2013 at 10:46 pm

    Hi William,
    Thanks for the comment and sorry for the late reply. You can always pass a reference of the model to the view and it’s even more proper MVC to do so than a Singleton. While certainly not necessary Singleton application model does 2 things: 1) it makes it easy to get a reference from anywhere and 2) it makes the data persist in memory even when switching activities until the application is destroyed. I hope that answers your question.

  • 25 Eric Yan // Jun 26, 2013 at 4:54 pm

    Hey Josh,

    Thanks for the wonderful tutorial on implementing MVC for an android project. Your sample source code has been a wonderful template and has been helping me learn the MVC design pattern.
    One thing that I noticed from this part of the tutorial was that you began creating your own views programatically. At first I was going to do the same for my current project, but I felt that it may be difficult for the next person who might take over the project. So as an alternative, I kept the usual
    setContentView(R.layout.activity_main);

    and instead passed the rootview through the constructor of our MainView.
    View v = getWindow().getDecorView().getRootView();
    MainView view = new MainView(v);

    My MainView does not extend LinearLayout. Instead, it uses the rootview to get the objects within the layout.
    v.findViewById(R.id.digit1);

    I was wondering if you can give me your feedback on whether this way of setting up the view for the MVC design would be a good approach.

    Thanks!

  • 26 Sabine Taahl // Jul 10, 2013 at 9:01 am

    Really nice way of implementing MVC in android. Thank you for this.
    I was wondering if you could help me by figuring out where to handle the options menu. As far as i understand in MVC the view should handle at first any input from the user.
    When the user hits an item of the action bar, the hook onOptionsItemSelected will be called. So i need to override this method. But its only available in the activity which is our controller. Do i have to skip this time the view and let the controller handle the user input? Or did i miss someting?

    Thank you very much. Your blog is really helpfull.

  • 27 musselwhizzle // Jul 10, 2013 at 12:04 pm

    Hi Sabine, Thanks for the comment. Remember Design Patterns like MVC are only a guide to help you write code. If you need to break the pattern and you know you are, feel free. Sometimes it’s just easier to. In the case of the onOptionsItemsSelected you can look at this hook method as being called for you when the hardware menu “view” button or overflow menu is clicked. From here, the controller decides what to do with which view item was selected in the onOptionsItemsSelected.

  • 28 Joey // Sep 29, 2013 at 9:24 am

    Great series of articles thanks!
    You propose your code as a starting point for new projects and I would like to do so but you don’t list a license for your code. Are you releasing it to the public domain? If not could you please indicate what you would consider fair use or attach a license?
    Thanks
    Joey

  • 29 musselwhizzle // Sep 30, 2013 at 2:53 pm

    Hi Joey, I will try to update the license soon. Until then please feel free to take, steal, borrow any code samples from this website. If you’d like you can give credit, but you don’t even need to do that. Hope you project goes great! Cheers, Josh

  • 30 Joey // Oct 9, 2013 at 9:26 am

    Thanks! I appreciate your approach and you blog :)
    At my day job we take great care not to misuse which while tedious at times I believe is the correct approach so I figured I should verify :)

  • 31 Trey Dempsey // Nov 12, 2013 at 2:13 pm

    I’m curious about setting data in the view before OnFinishInflate is called. I want to inflate my View from XML using View.inflate and I need to pass in a Model used in OnFinishInflate but I don’t want to use a singleton. Can i somehow pull it from the view using the Context parameter passed to View.inflate()?

  • 32 musselwhizzle // Nov 12, 2013 at 2:24 pm

    Hi Trey,
    Have a method called something like “init(…)” or “setData(…)” where you pass in the data to the view. Make another method called bindData() where all the work is actually done. In onFinishInflate and in init() both just call “bindData()” which checks if #1, there is data and #2 the view is inflated. Therefore it doesn’t matter the order in which the data has been set.

    void init(Object data) {
    this.data = data;
    bindData();
    }

    onFinishInflate() {
    // find views
    bindData();
    }

    void bindData() {
    if (this.data == null || aViewElement == null) return;
    // bind your data
    }

    You could also do this for individual properties. E.g.

    void setEyeColor(String color) {
    this.eyeColor = color;
    if (this.eyesView != null) {
    // apply color
    }
    }

    onFinishInflate() {
    eyesView = findViewById(R.id.myEyes);
    if (eyeColor != null) eyesView.setSomething(eyeColor);
    ……
    }

  • 33 Trey Dempsey // Nov 12, 2013 at 4:01 pm

    I’m not sure how i’d use View#init when using View.inflate().

    I ended up doing something like this:

    // Controller

    private PageModel pageModel;
    public PageModel getPageModel() {
    return pageModel;
    }

    onCreate() {
    View.inflate(this, R.id.page_view, null);
    view.setViewListener(viewListener);
    setContentView(view);
    }

    // View
    private PageModel pageModel;

    onFinishInflate() {
    pageModel = ((PageController)getContext()).getPageModel();
    // use page model …

  • 34 musselwhizzle // Nov 12, 2013 at 4:38 pm

    perhaps like:

    onCreate() {
    CustomView customView = (CustomView)LayoutInflater.from(this).inflate(R.layout.page_view, null, false);
    customView.init(….);
    customView.setSomething(….);
    customView.setViewListener(viewListener);
    setContentView(view);
    }

  • 35 Trey Dempsey // Nov 12, 2013 at 5:07 pm

    That’s no different than View.inflate().

    However it made me think about what I was doing with my model in OnFinishInflate().

    All i’m doing is binding to events from the model so I did this in the view:

    private PageModel pageModel;
    public void setPageModel(PageModel pageModel) {
    this.pageModel = pageModel;
    pageModel.addListener(PageModel.Event…..);
    }

    I made a few changes to your new-MVC example and network command example that i’ll eventually send your way.

    Specifically i decoupled message format parsing (XML, JSON, etc.) from the Command and moved it in to a base class for the Parser. That way the parse extends JsonParser and bam it knows how to parse Json messages and my Command class is still generic.

    I also created a base class for HttpCommand that I extend for each of GET, PUT, POST, DELETE.

    Adding request parameter signing on top of that (a la AWS signing v2) was trivial.

    Thanks for the excellent writing on this blog. It got me going with android development in less than a week. You write very accessible and understandable pieces. Keep up the good work.

  • 36 musselwhizzle // Nov 12, 2013 at 5:09 pm

    I think you missed the point. (I can’t remember the params for View.inflate so i just switched it out)
    #1 instantiate your view however you want.
    #2 cast it if necessary
    #3 call any method on it you want. setData(…)
    #4 profit!

    Glad you enjoy the blog. Good luck on your project!

  • 37 mdrozdo // Jan 12, 2014 at 6:55 pm

    Excellent update on the original architecture. I can see how this is much cleaner in terms of the communication between the view and controller. In your original posts, the message/handler based implementation seemed somewhat smelly – you’ve now made it strongly typed and removed the switch-case based handleMessage method. Such changes are always good design decisions :)

    Is there any particular reason to have the viewListener in a separate class instead of having the Activity implement the interface by itself?

    Thanks for this very useful series!

  • 38 androguy // Feb 5, 2014 at 10:48 am

    Great article! I find it more extensible to define layouts for custom Views in their own layout file, and inflate that in the CustomView constructor. That way in my Activity or Fragment layout, I can have one CustomView tag. This is like defining the layout programmatically, but it allows for the convenience of using layout files.

  • 39 Hindemburg // Mar 13, 2014 at 4:19 pm

    I request apologizes about my bad English. And I request apologizes too if this question is to obvious or very wrong. I think your website is the best explanation of how to apply the MVC to android. What I don’t understand is why it is to difficult to understand to me :(

    My question: is it indispensable that the View listens to the changes of the model?

    Normally, what I do is obtain the data from a webservice or database (with an async task normally) or intent in my controller/activity. Then I send the data (in a form of a pojo normally) to the view and call a method that renders the data.

    I suppose my aproach is totally wrong… :-(

    Thanks in advance.

  • 40 musselwhizzle // Mar 13, 2014 at 5:10 pm

    Your approach is totally fine and honestly, that’s exactly how I do most of my projects as well. While that I wrote is MVC, MVC doesn’t necessarily fit all too well on Android. Keep doing what you’re doing. It’s more about delegation of responsibilities and it sounds like you are doing that well.

  • 41 Venkatesan // Mar 21, 2014 at 6:34 am

    Hi,
    Thanks for your very good post to study MVC pattern i Android. I was hoping you could do another post at some point demonstrating the following:

    - How web-service calls are integrated into the MVC pattern.

    - How exactly you propagate model change events to multiple views in your application.

    - Tied to the above, how you store the model data that is shared by multiple views/activities. Do you store it centrally somewhere?

    Please help me.
    Venkatesan.R

  • 42 Yini // Apr 18, 2014 at 12:31 am

    Great Article!

    One question though:
    How the controller/activity survives a configuration change?

    Can you please give me some pointers here?

    Thanks,
    Yini

  • 43 Jack // May 16, 2014 at 1:20 pm

    Hey musselwhizzle,
    First I’d like to say that this is probably the best resource on Android MVC in the internet so thank you for that!
    Other than that I have a question related to list views and the whole adapter pattern used in Android.
    I have a list view that holds fairly complex items which include multiple labels, widgets and buttons in each row. In addition I need to be able to change a row view based on a property of the model behind it – to support different layouts through the state pattern. I came up with a relatively flexible way of setting this up where I have an adapter that hold the models and using a factory given to it, creates proper views for the list view to use.
    The list view that uses this adapter is in its own view that is bound to a model and controller based on your article.
    So my question is whose responsibility is to handle click events of buttons in each row’s view and how to hook this up? Also I would like to know if there is a better way to implement complex rows in list views.

    Thanks a lot.
    Jack

  • 44 musselwhizzle // May 16, 2014 at 2:32 pm

    Hi Jack. The main concern with ListViews/Adapters is performance. I would put everything else above that including architecture. Event broadcasting, data binding, and complex objects and creations can slow all of that down. OOP are guidelines and never rules. With that said I generally approach my ListViews/Adapter in 1 of 2 ways: #1 The Holder pattern. This is useful for simple item. #2 I make a custom item renderer that subclasses something like RelativeLayout. You can do much more complicated things that what the Holder pattern would allow for you. In your case, it sounds like just a simple override of Adapter getViewTypeCount and getItemViewType coupled with a notifyDataSetChanged() would do the trick for you and let the Adapter be smart and your item renderers dumb.

Leave a Comment

Powered by sweet Captcha