During the
development of games and applications are often situations when to have
developed in each Activity to write the same code. Then transfer it to other
projects. In this article I would like to talk about how you can make life
easier when creating the next Activity in the application.
Theory
What we often use when creating a new Activity? Of course this setting displays a View (method setContentView()), sending statistics, using Wake Lock, logging methods, start and stop the music, and more. Why do none of these methods to transfer to another class, and then extend from it in our Activity.Practice
Develop an abstract class: SceletonActivity. Subclass android.app.Activity, so you can use the appropriate methods.public abstract class SceletonActivity extends Activity { }
In this
article, I will add to our "skeleton" traceability applications pause
using Wake Lock, logging and sending statistics.
Add the
basic methods used in our Activity. I use for logging class, I described in the
article "Logging in Android». As well add the attribute protected String
tag. It will be used to store the current class name.
protected String tag; // the class name for logging @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); LogSystem.w(tag, "onCreate()"); } @Override protected void onPause() { super.onPause(); LogSystem.w(tag, "onPause()"); } @Override protected void onResume() { super.onResume(); LogSystem.w(tag, "onResume()"); this.mPaused = false; wlAsquire(); } @Override protected void onDestroy() { super.onDestroy(); LogSystem.w(tag, "onDestroy()"); } @Override protected void onStart() { super.onStart(); LogSystem.w(tag, "onStart()"); } @Override protected void onStop() { super.onStop(); LogSystem.w(tag, "onStop()"); }
The next stage in the development of our
"skeleton" - tracking pauses in the application. To do this, we add
an attribute protected boolean mPaused. And slightly modify our methods:
protected boolean mPaused; // monitors the pause in the application @Override protected void onPause() { super.onPause(); LogSystem.w(tag, "onPause()"); this.mPaused = true; } @Override protected void onResume() { super.onResume(); LogSystem.w(tag, "onResume()"); this.mPaused = false; }
What you can do this attribute, I will show
later in this article.
Now we need to install the appropriate View and
Tag for Activity, and initialize all of the elements of the user interface of
our Activity. For this we will use abstract methods:
protected abstract void initInterface(); // initialization interface protected abstract void setAttr(); // set the attributes of the class
Their implementation founded in the Activity,
which will be the descendants of SceletonActivity. Calling these methods must
be placed in the method onCreate() of our "skeleton":
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setAttr(); LogSystem.w(tag, "onCreate()"); setContentView(view); initInterface(); }
We also want to send statistics to our use of
services (eg, Google Analitics or Flurry). To do this, we add the following
method:
public void trackSupportedApp(String activity, Mapmap) { LogSystem.w(tag, "trackSupportedApp(" + activity + ")"); }
Instead of logging, you must add code to send
statistics for services you use. For example, for Flurry code may look
like this:
public static void trackSupportedApp(String activity, Mapmap) { if (activity == null || activity.length() == 0) return; if (map == null) FlurryAgent.logEvent(activity); else FlurryAgent.logEvent(activity, map); }
And lastly I will add WakeLock, that our
application does not screen turns off while you work.
For this we need 3 methods:
/** * Initialization WakeLock */ private void initWl() { if (wl == null) { PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "org.snowpard.projects.five"); } } /** * Runs the requested function WakeLock */ public void wlAsquire() { try { if (wl != null) wl.acquire(); }catch (Exception e) { } } /** * Stop the execution of the requested function WakeLock */ public void wlRelease() { try { if (wl != null) wl.release(); }catch (Exception e) { } }
Again change our methods to use the new
features:
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setAttr(); LogSystem.w(tag, "onCreate()"); setContentView(view); trackSupportedApp(tag, null); initWl(); initInterface(); } @Override protected void onPause() { super.onPause(); LogSystem.w(tag, "onPause()"); this.mPaused = true; wlRelease(); } @Override protected void onResume() { super.onResume(); LogSystem.w(tag, "onResume()"); this.mPaused = false; wlAsquire(); }
Use SceletonActivity
Now I'll show how to simplify the design of our Activity. Develop an application that contains two Activity and buttons to move between them.
Example strings.xml
<resources>
<string name="btn_next">Next Activity</string>
<string name="btn_previous">Previous Activity</string>
<string name="app_name">Skeleton Example</string>
</resources>
An example of the layout file for our Activity:
first.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:id="@+id/btn_next"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/btn_next" />
</LinearLayout>
second.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:id="@+id/btn_previous"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/btn_previous" />
</LinearLayout>
And classes:
FirstActivity.java
public class FirstActivity extends SceletonActivity { @Override protected void initInterface() { Button btn = (Button)findViewById(R.id.btn_next); btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(FirstActivity.this, SecondActivity.class); startActivity(intent); } }); } @Override protected void setAttr() { this.tag = FirstActivity.class.getSimpleName(); this.view = R.layout.first; } }
SecondActivity.java
public class SecondActivity extends SceletonActivity { @Override protected void initInterface() { Button btn = (Button)findViewById(R.id.btn_previous); btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { finish(); } }); } @Override protected void setAttr() { this.tag = SecondActivity.class.getSimpleName(); this.view = R.layout.second; } }
As you can see, there is no duplicate code, the
code itself is compact enough, and our Activity versatile.
Do not forget to add created Activity in
AndroidManifest:
<activity
android:name=".FirstActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN"
/>
<category android:name="android.intent.category.LAUNCHER"
/>
</intent-filter>
</activity>
<activity
android:name=".SecondActivity"
android:label="@string/app_name" >
</activity>
Attribute mPaused
As I promised, I will tell a little about the attribute mPaused, which is used to track a pause in the application. How can it be used? It happens that when you press the button, the effect is not immediate (the device are different), and user can perform second press, which, for example, it would be in your application is not desirable. For this and used mPaused. Example of use:btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (!mPaused) { Intent intent = new Intent(FirstActivity.this, SecondActivity.class); startActivity(intent); mPaused = true; } } });
No comments:
Post a Comment