I’ve been learning android development (in Eclipse) the past week. I’m following online courses and reading books as much as possible, whilst also digging in and trying to write an application. I’m playing with GreenDroid in an application and I have a real life example to run by you.
I have my main application class as follows:
public class InfoActivity extends GDListActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle(R.string.info_activity_title);
ItemAdapter adapter = new ItemAdapter(this);
adapter.add(createTextItem(R.string.info_about, AboutActivity.class));
adapter.add(createTextItem(R.string.info_terms, TermsActivity.class));
adapter.add(createTextItem(R.string.info_privacy, PrivacyActivity.class));
setListAdapter(adapter);
}
private TextItem createTextItem(int stringId, Class<?> klass) {
final TextItem textItem = new TextItem(getString(stringId));
textItem.setTag(klass);
return textItem;
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
final TextItem textItem = (TextItem) l.getAdapter().getItem(position);
Intent intent = new Intent(InfoActivity.this, (Class<?>) textItem.getTag());
startActivity(intent);
}
}
Everything works well. Here’s my question – how can I re-use the code from one class in others but take a variable and change it based on that? – the line
adapter.add(createTextItem(R.string.info_about, AboutActivity.class));
requires another activity class to be created. The code for that is as follows:
public class AboutActivity extends GDActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle(R.string.info_about);
setActionBarContentView(R.layout.info_template);
WebView engine = (WebView) findViewById(R.id.web_view);
engine.setBackgroundColor(0);
engine.setBackgroundResource(R.drawable.bg);
engine.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
engine.getSettings().setBuiltInZoomControls(true);
engine.loadUrl("http://m.example.com/about.html");
engine.setWebViewClient(new WebViewWithin());
}
}
The other two classes TermsActivity and PrivacyActivity are identical except for two parts:
setTitle(R.string.info_about);
and
engine.loadUrl("http://m.example.com/about.html");
Which in the latter activity example would be:
setTitle(R.string.info_privacy);
and
engine.loadUrl("http://m.example.com/privacy.html");
As this is my first time learning Java, I’m still getting my head around lots of the concepts. I’m well versed in PHP and would write a function that could take a string variable and place it into the function (effectively re-using the same code), such as:
This is PHP and Java pseudo-code to get my point across.
<?php
function aboutSecondaryPage( $page ) {
setTitle( this.getString( R.string.info_ . $page ) );
engine.loadUrl("http://m.example.com/" . $page . ".html" );
}
?>
So given these examples, is there a better way for each of these three classes to re-use the same code and call it from another class. Any guidance would be useful. As is, everything works, I’m just seeking to learn from those with much greater experience.
Thank you!
CURRENT SOLUTION (AFTER KURTIS EXCELLENT ASSISTANCE)
My parent activity method which the other three activities inherit from:
public class InfoSecActivity extends GDListActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle(getTitleResourceId());
setActionBarContentView(R.layout.info_template);
WebView engine = (WebView) findViewById(R.id.web_view);
engine.setBackgroundColor(0);
engine.setBackgroundResource(R.drawable.bg);
engine.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
engine.getSettings().setBuiltInZoomControls(true);
engine.loadUrl(getUrlToLoad());
engine.setWebViewClient(new WebViewWithin());
}
public int getTitleResourceId() {
return 0;
}
public String getUrlToLoad() {
return null;
}
}
An example of sub-class which is called from InfoActivity class.
public class AboutActivity extends InfoSecActivity {
public int getTitleResourceId() {
return R.string.info_about;
}
public String getUrlToLoad() {
return "http://m.example.com/about.html";
}
}
It works beautifully, but in the interest of learning best practices – have I done this the best way and anything to be aware of (potential problems with this methodology)? This is mainly for Kurtis – hope you read this again 🙂
You could always take the code that’s getting reused and extract it up into an abstract parent class. So in this parent class you’d put all the code that is shared by all of your activities. But where the code differs, you call abstract methods that you implement concretely in each of the subclasses. This is called the Template Design Patter. So for instance, in your onCreate method of your abstract parent class you’d do this:
In this case, you would then declare
getTitleResourceId()andgetUrlToLoad()as abstract in the parent class. Then in each subclass, the only piece of code you have to write is the definition for thegetTitleResourceId()andgetUrlToLoad()methods. For example, in your Privacy activity you’d have these methods returnR.string.info_privacyand"http://m.example.com/privacy.html"respectively. But in your other subclasses, you’d have them return different values.