Во время разработки игр и приложений часто возникают
ситуации, когда приходиться в каждом разработанном Activity писать один и тот же код. Потом
переносить его в другие проекты. В этой статье я хотел бы рассказать о том, как
можно облегчить жизнь при создании очередного Activity в приложении.
Теория
Что чаще всего мы используем при создании нового Activity? Конечно это
установка отображаемого View
(метод setContentView()),
отправка статистики, использование Wake Lock, логирование методов, запуск и остановка музыки и много
другое. Почему бы все эти методы не перенести в один класс, и затем
наследоваться от него в нашем Activity.
Практика
Разработаем абстрактный класс: SceletonActivity. Наследуемся
от android.app.Activity, чтобы можно было использовать соответствующие методы.
public abstract class SceletonActivity extends Activity {
}
В этой статье я добавлю для нашего «скелета» возможность
отследить паузу приложения, использование Wake Lock, логирование и отправку статистики.
Добавим основные используемые методы в наш Activity. Для логирования я использую
класс, описанный мною в статье «Логирование в Android». Так же добавим атрибут protected
String tag. Он будет использоваться для хранения текущего имени класса.
protected String tag; // Имя класса для логирования
@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()");
}
@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()");
}
Следующий этап разработки нашего «скелета» - отслеживание
паузы в приложении. Для этого мы добавим атрибут protected boolean mPaused. И
немного изменим наши методы:
protected boolean mPaused; // отслеживание паузы в приложении
@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;
}
Для чего можно
использовать этот атрибут я покажу чуть позже в этой статье.
Теперь нам необходимо
установить для Activity соответствующее View и Tag,
а также инициализировать все элементы UI нашего Activity. Для этого у нас будут
использоваться абстрактные методы:
protected abstract void initInterface(); // Инициализация интерфейса protected abstract void setAttr(); // Установка атрибутов класса
Их реализация заложена в
тех Activity, которые
будут наследниками для SceletonActivity. Вызов этих методов необходимо
поместить в метод onCreate()
нашего «скелета»:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setAttr();
LogSystem.w(tag, "onCreate()");
setContentView(view);
initInterface();
}
Так же мы хотим
отправлять статистику на используемый нами сервис (например, Google Analitics или Flurry).
Для этого мы добавим следующий метод:
public void trackSupportedApp(String activity, Mapmap) { LogSystem.w(tag, "trackSupportedApp(" + activity + ")"); }
Вместо логирования
необходимо добавит код отправки статистики для используемого вами сервиса.
Например, для Flurry
код может выглядеть следующим образом:
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); }
И на последок я добавлю WakeLock, чтобы наше
приложение не отключало экран во время работы.
Для этого нам необходимо
3 метода:
/**
* Инициализация 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");
}
}
/**
* Запускаем выполнение запрошенных функций WakeLock
*/
public void wlAsquire()
{
try
{
if (wl != null)
wl.acquire();
}catch (Exception e) {
}
}
/**
* Останавливаем выполнение запрошенных функций WakeLock
*/
public void wlRelease()
{
try
{
if (wl != null)
wl.release();
}catch (Exception e) {
}
}
Снова изменим наши
методы для использования новых функций:
@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();
}
Использование SceletonActivity
Теперь я покажу, как
упростилась работы при разработке наших Activity. Разработаем приложение, содержащее 2 Activity и кнопки для перемещения между
ними.
Пример файла strings.xml
<resources>
<string name="btn_next">Следующее
Activity</string>
<string name="btn_previous">Предыдущее Activity</string>
<string name="app_name">Skeleton Example</string>
</resources>
Пример файлов макетов
для наших 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>
И сами классы:
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;
}
}
Как видите,
повторяющегося кода нет, сам код достаточно компактен, а наши Activity многофункциональны.
Не забудьте добавит
созданные Activity в 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>
Атрибут mPaused
Как я и обещал, расскажу
немного об атрибуте mPaused, который используется для отслеживания паузы в
приложении. Как его можно использовать? Бывает, что при нажатии на кнопку,
действие происходит не сразу (девайсы разные бывают), и пользователь может
произвести повторное нажатие, которое, например, было бы в вашем приложении не желательно.
Для этого и используется mPaused. Пример использования:
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (!mPaused)
{
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivity(intent);
mPaused = true;
}
}
});
Ссылки
Исходные коды данного проекта можно скачать отсюда: zip
Комментариев нет:
Отправить комментарий