Skip to content

Commit 08135aa

Browse files
romannurikAndroid Git Automerger
authored andcommitted
am 38e09c3: docs: Android Training: Creating Backward-Compatible UIs class
* commit '38e09c3ddb7da47a23bf4221ab678e058c7e923a': docs: Android Training: Creating Backward-Compatible UIs class
2 parents f872e0b + 38e09c3 commit 08135aa

File tree

12 files changed

+575
-1
lines changed

12 files changed

+575
-1
lines changed
11.7 KB
Loading
12.8 KB
Loading
22.1 KB
Loading
17 KB
Loading
15.8 KB
Loading

docs/html/resources/resources_toc.cs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,31 @@
227227
</li>
228228
</ul>
229229
</li>
230-
230+
231+
<li class="toggle-list">
232+
<div><a href="<?cs var:toroot ?>training/backward-compatible-ui/index.html">
233+
<span class="en">Creating Backward-Compatible UIs<span class="new">&nbsp;new!</span></span>
234+
</a></div>
235+
<ul>
236+
<li><a href="<?cs var:toroot ?>training/backward-compatible-ui/abstracting.html">
237+
<span class="en">Abstracting the New APIs</span>
238+
</a>
239+
</li>
240+
<li><a href="<?cs var:toroot ?>training/backward-compatible-ui/new-implementation.html">
241+
<span class="en">Proxying to the New APIs</span>
242+
</a>
243+
</li>
244+
<li><a href="<?cs var:toroot ?>training/backward-compatible-ui/older-implementation.html">
245+
<span class="en">Creating an Implementation with Older APIs</span>
246+
</a>
247+
</li>
248+
<li><a href="<?cs var:toroot ?>training/backward-compatible-ui/using-component.html">
249+
<span class="en">Using the Version-Aware Component</span>
250+
</a>
251+
</li>
252+
</ul>
253+
</li>
254+
231255
<li class="toggle-list">
232256
<div><a href="<?cs var:toroot ?>training/enterprise/index.html">
233257
<span class="en">Developing for Enterprise</span>
566 KB
Binary file not shown.
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
page.title=Abstracting the New APIs
2+
parent.title=Creating Backward-Compatible UIs
3+
parent.link=index.html
4+
5+
trainingnavtop=true
6+
next.title=Proxying to the New APIs
7+
next.link=new-implementation.html
8+
9+
@jd:body
10+
11+
<div id="tb-wrapper">
12+
<div id="tb">
13+
14+
<h2>This lesson teaches you to:</h2>
15+
<ul>
16+
<li><a href="#prepare-abstraction">Prepare for Abstraction</a></li>
17+
<li><a href="#create-abstract-tab">Create an Abstract Tab Interface</a></li>
18+
<li><a href="#abstract-actionbar-tab">Abstract ActionBar.Tab</a></li>
19+
<li><a href="#abstract-actionbar-methods">Abstract ActionBar Tab Methods</a></li>
20+
</ul>
21+
22+
<h2>You should also read</h2>
23+
<ul>
24+
<li><a href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a></li>
25+
<li><a href="{@docRoot}guide/topics/ui/actionbar.html#Tabs">Action Bar Tabs</a></li>
26+
</ul>
27+
28+
<h2>Try it out</h2>
29+
30+
<div class="download-box">
31+
<a href="http://developer.android.com/shareables/training/TabCompat.zip"
32+
class="button">Download the sample app</a>
33+
<p class="filename">TabCompat.zip</p>
34+
</div>
35+
36+
</div>
37+
</div>
38+
39+
<p>Suppose you want to use <a href="{@docRoot}guide/topics/ui/actionbar.html#Tabs">action bar tabs</a> as the primary form of top-level navigation in your application. Unfortunately, the {@link android.app.ActionBar} APIs are only available in Android 3.0 or later (API level 11+). Thus, if you want to distribute your application to devices running earlier versions of the platform, you need to provide an implementation that supports the newer API while providing a fallback mechanism that uses older APIs.</p>
40+
41+
<p>In this class, you build a tabbed user interface (UI) component that uses abstract classes with version-specific implementations to provide backward-compatibility. This lesson describes how to create an abstraction layer for the new tab APIs as the first step toward building the tab component.</p>
42+
43+
<h2 id="prepare-abstraction">Prepare for Abstraction</h2>
44+
45+
<p><a href="http://en.wikipedia.org/wiki/Abstraction_(computer_science)">Abstraction</a> in the Java programming language involves the creation of one or more interfaces or abstract classes to hide implementation details. In the case of newer Android APIs, you can use abstraction to build version-aware components that use the current APIs on newer devices, and fallback to older, more compatible APIs on older devices.</p>
46+
47+
<p>When using this approach, you first determine what newer classes you want to be able to use in a backward compatible way, then create abstract classes, based on the public interfaces of the newer classes. In defining the abstraction interfaces, you should mirror the newer API as much as possible. This maximizes forward-compatibility and makes it easier to drop the abstraction layer in the future when it is no longer necessary.</p>
48+
49+
<p>After creating abstract classes for these new APIs, any number of implementations can be created and chosen at runtime. For the purposes of backward-compatibility, these implementations can vary by required API level. Thus, one implementation may use recently released APIs, while others can use older APIs.</p>
50+
51+
<h2 id="create-abstract-tab">Create an Abstract Tab Interface</h2>
52+
53+
<p>In order to create a backward-compatible version of tabs, you should first determine which features and specific APIs your application requires. In the case of top-level section tabs, suppose you have the following functional requirements:</p>
54+
55+
<ol>
56+
<li>Tab indicators should show text and an icon.</li>
57+
<li>Tabs can be associated with a fragment instance.</li>
58+
<li>The activity should be able to listen for tab changes.</li>
59+
</ol>
60+
61+
<p>Preparing these requirements in advance allows you to control the scope of your abstraction layer. This means that you can spend less time creating multiple implementations of your abstraction layer and begin using your new backward-compatible implementation sooner.</p>
62+
63+
<p>The key APIs for tabs are in {@link android.app.ActionBar} and {@link android.app.ActionBar.Tab ActionBar.Tab}. These are the APIs to abstract in order to make your tabs version-aware. The requirements for this example project call for compatibility back to Eclair (API level 5) while taking advantage of the new tab features in Honeycomb (API Level 11). A diagram of the class structure to support these two implementations and their abstract base classes (or interfaces) is shown below.</p>
64+
65+
<img src="{@docRoot}images/training/backward-compatible-ui-classes.png"
66+
alt="Class diagram of abstract base classes and version-specific implementations." id="figure-classes">
67+
68+
<p class="img-caption"><strong>Figure 1.</strong> Class diagram of abstract base classes and version-specific implementations.</p>
69+
70+
<h2 id="abstract-actionbar-tab">Abstract ActionBar.Tab</h2>
71+
72+
<p>Get started on building your tab abstraction layer by creating an abstract class representing a tab, that mirrors the {@link android.app.ActionBar.Tab ActionBar.Tab} interface:</p>
73+
74+
<pre>
75+
public abstract class CompatTab {
76+
...
77+
public abstract CompatTab setText(int resId);
78+
public abstract CompatTab setIcon(int resId);
79+
public abstract CompatTab setTabListener(
80+
CompatTabListener callback);
81+
public abstract CompatTab setFragment(Fragment fragment);
82+
83+
public abstract CharSequence getText();
84+
public abstract Drawable getIcon();
85+
public abstract CompatTabListener getCallback();
86+
public abstract Fragment getFragment();
87+
...
88+
}
89+
</pre>
90+
91+
<p>You can use an abstract class instead of an interface here to simplify the implementation of common features such as association of tab objects with activities (not shown in the code snippet).</p>
92+
93+
<h2 id="abstract-actionbar-methods">Abstract ActionBar Tab Methods</h2>
94+
95+
<p>Next, define an abstract class that allows you to create and add tabs to an activity, like {@link android.app.ActionBar#newTab ActionBar.newTab()} and {@link android.app.ActionBar#addTab ActionBar.addTab()}:</p>
96+
97+
<pre>
98+
public abstract class TabHelper {
99+
...
100+
101+
public CompatTab newTab(String tag) {
102+
// This method is implemented in a later lesson.
103+
}
104+
105+
public abstract void addTab(CompatTab tab);
106+
107+
...
108+
}
109+
</pre>
110+
111+
<p>In the next lessons, you create implementations for <code>TabHelper</code> and <code>CompatTab</code> that work across both older and newer platform versions.</p>
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
page.title=Creating Backward-Compatible UIs
2+
3+
trainingnavtop=true
4+
startpage=true
5+
next.title=Abstracting the New Implementation
6+
next.link=abstracting.html
7+
8+
@jd:body
9+
10+
<div id="tb-wrapper">
11+
<div id="tb">
12+
13+
<h2>Dependencies and prerequisites</h2>
14+
15+
<ul>
16+
<li>API level 5</li>
17+
<li><a href="{@docRoot}sdk/compatibility-library.html">The Android Support Package</a></li>
18+
</ul>
19+
20+
<h2>You should also read</h2>
21+
22+
<ul>
23+
<li><a href="{@docRoot}resources/samples/ActionBarCompat/index.html">ActionBarCompat</a></li>
24+
<li><a href="http://android-developers.blogspot.com/2010/07/how-to-have-your-cupcake-and-eat-it-too.html">How to have your (Cup)cake and eat it too</a></li>
25+
</ul>
26+
27+
<h2>Try it out</h2>
28+
29+
<div class="download-box">
30+
<a href="http://developer.android.com/shareables/training/TabCompat.zip"
31+
class="button">Download the sample app</a>
32+
<p class="filename">TabCompat.zip</p>
33+
</div>
34+
35+
</div>
36+
</div>
37+
38+
<p>This class demonstrates how to use UI components and APIs available in newer versions of Android in a backward-compatible way, ensuring that your application still runs on previous versions of the platform.</p>
39+
40+
<p>Throughout this class, the new <a href="{@docRoot}guide/topics/ui/actionbar.html#Tabs">Action Bar Tabs</a> feature introduced in Android 3.0 (API level 11) serves as the guiding example, but you can apply these techniques to other UI components and API features.</p>
41+
42+
<h2 id="lessons">Lessons</h2>
43+
44+
45+
<dl>
46+
<dt><strong><a href="abstracting.html">Abstracting the New APIs</a></strong></dt>
47+
<dd>Determine which features and APIs your application needs. Learn how to define application-specific, intermediary Java interfaces that abstract the implementation of the UI component to your application.</dd>
48+
49+
<dt><strong><a href="new-implementation.html">Proxying to the New APIs</a></strong></dt>
50+
<dd>Learn how to create an implementation of your interface that uses newer APIs.</dd>
51+
52+
<dt><strong><a href="older-implementation.html">Creating an Implementation with Older APIs</a></strong></dt>
53+
<dd>Learn how to create a custom implementation of your interface that uses older APIs.</dd>
54+
55+
<dt><strong><a href="using-component.html">Using the Version-Aware Component</a></strong></dt>
56+
<dd>Learn how to choose an implementation to use at runtime, and begin using the interface in your application.</dd>
57+
</dl>
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
page.title=Proxying to the New APIs
2+
parent.title=Creating Backward-Compatible UIs
3+
parent.link=index.html
4+
5+
trainingnavtop=true
6+
previous.title=Abstracting the New APIs
7+
previous.link=abstracting.html
8+
next.title=Creating an Implementation with Older APIs
9+
next.link=older-implementation.html
10+
11+
@jd:body
12+
13+
<div id="tb-wrapper">
14+
<div id="tb">
15+
16+
<h2>This lesson teaches you to:</h2>
17+
<ol>
18+
<li><a href="#new-tabs">Implement Tabs Using New APIs</a></li>
19+
<li><a href="#compattabhoneycomb">Implement CompatTabHoneycomb</a></li>
20+
<li><a href="#tabhelperhoneycomb">Implement TabHelperHoneycomb</a></li>
21+
</ol>
22+
23+
<h2>You should also read</h2>
24+
<ul>
25+
<li><a href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a></li>
26+
<li><a href="{@docRoot}guide/topics/ui/actionbar.html#Tabs">Action Bar Tabs</a></li>
27+
</ul>
28+
29+
<h2>Try it out</h2>
30+
31+
<div class="download-box">
32+
<a href="http://developer.android.com/shareables/training/TabCompat.zip"
33+
class="button">Download the sample app</a>
34+
<p class="filename">TabCompat.zip</p>
35+
</div>
36+
37+
</div>
38+
</div>
39+
40+
<p>This lesson shows you how to subclass the <code>CompatTab</code> and <code>TabHelper</code> abstract classes and use new APIs. Your application can use this implementation on devices running a platform version that supports them.</p>
41+
42+
<h2 id="new-tabs">Implement Tabs Using New APIs</h2>
43+
44+
<p>The concrete classes for <code>CompatTab</code> and <code>TabHelper</code> that use newer APIs are a <em>proxy</em> implementation. Since the abstract classes defined in the previous lesson mirror the new APIs (class structure, method signatures, etc.), the concrete classes that use these newer APIs simply proxy method calls and their results.</p>
45+
46+
<p>You can directly use newer APIs in these concrete classes&mdash;and not crash on earlier devices&mdash;because of lazy class loading. Classes are loaded and initialized on first access&mdash;instantiating the class or accessing one of its static fields or methods for the first time. Thus, as long as you don't instantiate the Honeycomb-specific implementations on pre-Honeycomb devices, the Dalvik VM won't throw any {@link java.lang.VerifyError} exceptions.</p>
47+
48+
<p>A good naming convention for this implementation is to append the API level or platform version code name corresponding to the APIs required by the concrete classes. For example, the native tab implementation can be provided by <code>CompatTabHoneycomb</code> and <code>TabHelperHoneycomb</code> classes, since they rely on APIs available in Android 3.0 (API level 11) or later.</p>
49+
50+
<img src="{@docRoot}images/training/backward-compatible-ui-classes-honeycomb.png"
51+
alt="Class diagram for the Honeycomb implementation of tabs." id="figure-classes">
52+
53+
<p class="img-caption"><strong>Figure 1.</strong> Class diagram for the Honeycomb implementation of tabs.</p>
54+
55+
<h2 id="compattabhoneycomb">Implement CompatTabHoneycomb</h2>
56+
57+
<p><code>CompatTabHoneycomb</code> is the implementation of the <code>CompatTab</code> abstract class that <code>TabHelperHoneycomb</code> uses to reference individual tabs. <code>CompatTabHoneycomb</code> simply proxies all method calls to its contained {@link android.app.ActionBar.Tab} object.</p>
58+
59+
<p>Begin implementing <code>CompatTabHoneycomb</code> using the new {@link android.app.ActionBar.Tab ActionBar.Tab} APIs:</p>
60+
61+
<pre>
62+
public class CompatTabHoneycomb extends CompatTab {
63+
// The native tab object that this CompatTab acts as a proxy for.
64+
ActionBar.Tab mTab;
65+
...
66+
67+
protected CompatTabHoneycomb(FragmentActivity activity, String tag) {
68+
...
69+
// Proxy to new ActionBar.newTab API
70+
mTab = activity.getActionBar().newTab();
71+
}
72+
73+
public CompatTab setText(int resId) {
74+
// Proxy to new ActionBar.Tab.setText API
75+
mTab.setText(resId);
76+
return this;
77+
}
78+
79+
...
80+
// Do the same for other properties (icon, callback, etc.)
81+
}
82+
</pre>
83+
84+
<h2 id="tabhelperhoneycomb">Implement TabHelperHoneycomb</h2>
85+
86+
<p><code>TabHelperHoneycomb</code> is the implementation of the <code>TabHelper</code> abstract class that proxies method calls to an actual {@link android.app.ActionBar}, obtained from its contained {@link android.app.Activity}.</p>
87+
88+
<p>Implement <code>TabHelperHoneycomb</code>, proxying method calls to the {@link android.app.ActionBar} API:</p>
89+
90+
<pre>
91+
public class TabHelperHoneycomb extends TabHelper {
92+
ActionBar mActionBar;
93+
...
94+
95+
protected void setUp() {
96+
if (mActionBar == null) {
97+
mActionBar = mActivity.getActionBar();
98+
mActionBar.setNavigationMode(
99+
ActionBar.NAVIGATION_MODE_TABS);
100+
}
101+
}
102+
103+
public void addTab(CompatTab tab) {
104+
...
105+
// Tab is a CompatTabHoneycomb instance, so its
106+
// native tab object is an ActionBar.Tab.
107+
mActionBar.addTab((ActionBar.Tab) tab.getTab());
108+
}
109+
110+
// The other important method, newTab() is part of
111+
// the base implementation.
112+
}
113+
</pre>

0 commit comments

Comments
 (0)