关闭

关于Google 教程中 Manage the Activity Lifecycle 示例的学习

标签: 谷歌ui
297人阅读 评论(0) 收藏 举报
分类:

Google 关于管理Activity生命周期的示例

昨天晚上我看了Google training里面Manage the Activity Lifecycle这一节,看了以后学到很多以前看书,看视频都没有了解过的东西,Google关于如何恰当地使用这些方法来是我们的APP运行流畅,符合用户的预期给出了很好的指导意见,比如Pause()里面释放不需要的系统资源,停止UI动画等消耗内存的东西,不要进行密集CPU操作以影响Activity的过渡等等,还有SaveInstanceStates()作用及用法的详细讲解。。。。反正好多好多了。

于是,我就忍不住下载了官方示例,看看Google的实例APP是怎么样的。在Studio里面运行一看,果然不一样。一般的教程都是给你看看Log就好了吧,而且只运行一个Activity,让你看看单个Activity的变化是怎么样的。瞬间差距就出来了。。。。。Google的示例不仅仅将Activity的数量范围变大到3个,还用图形化的方式更直观的给我们展示了Activity生命周期的变化过程。

有图为证:
Activity A

Activity B

DIALOG Activity

看着确实是厉害了很多呢,如果只是从图形化的角度去看看Activity的生命周期在各种情况下的变化,学习Activity生命周期的目的应该达到了,但我很好奇他是怎么做出来,因为我是Android新手,所以就看了看源码,下面是我从源码里面的学到东西的摘要。

如果大家对这个示例也感兴趣,可以点击这里进行示例的下载.


第一个问题:

  • 如何在多个Activity切换的时候,追踪Activity的状态变化信息,然后显示出来?

第一个回答:

  • 首先在每个Activity使用一样的布局,然后定义一个工具类A来存贮所有Activity变化的状态信息,所有的Activity共用一个静态工具类A变量,这保证了状态信息的共享。然后定义一个工具类B,分别在每个Activity的不同状态打印信息。

好了,让我们先看一下工具类A的代码吧。

public class StatusTracker {
  private Map<String, String> mStatusMap;
  private List<String> mMethodList;
  private static StatusTracker ourInstance = new StatusTracker();
  private static final String STATUS_SUFFIX = "ed";

  public static StatusTracker getInstance() {
    return ourInstance;
  }

  private StatusTracker() {
    mStatusMap = new LinkedHashMap<String, String>();
    mMethodList = new ArrayList<String>();
  }

  public List<String> getMethodList() {
    return mMethodList;
  }

  public void clear() {
    mMethodList.clear();
    mStatusMap.clear();
  }

  /**
   * Adds the status value for the given activityName into the Map.
   *
   * @param activityName
   * @param status
   */
  public void setStatus(String activityName, String status) {
    mMethodList.add(activityName + "." + status + "()");
    if (mStatusMap.containsKey(activityName)) mStatusMap.remove(activityName);
    mStatusMap.put(activityName, status);
  }

  /**
   * Gets the status value for the given activityName.
   *
   * @param activityName
   * @return
   */
  public String getStatus(String activityName) {
    String status = mStatusMap.get(activityName);
    status = status.substring(2, status.length());

    // String manipulation to ensure the status value is spelled correctly.
    if (status.endsWith("e")) {
      status = status.substring(0, status.length() - 1);
    }
    if (status.endsWith("p")) {
      status = status + "p";
    }
    status = status + STATUS_SUFFIX;
    return status;
  }

  public Set<String> keySet() {
    return mStatusMap.keySet();
  }
}

首先,我们看到 StatusTracker 这个类内部定义了一个静态的自身变量和 getInstance() 方法,这样我们只要在不同的地方直接调用这个静态方法就能得到相同的 StatusTracker 变量了。

public class StatusTracker {
  private Map<String, String> mStatusMap;
  private List<String> mMethodList;
  private static StatusTracker ourInstance = new StatusTracker();
  private static final String STATUS_SUFFIX = "ed";

  public static StatusTracker getInstance() {
    return ourInstance;
  }
  。。。。

然后我们再看它存贮状态信息的代码 它定义了一个 Map 用来存贮不同Activity状态(最多3个),定义了一个List用来存贮所有Activity状态变化的历史信息。因为Map不能存贮重复的键值对,而List可以存储重复的信息。

然后通过 setStatus 这个方法来更新Activity最新的状态。

public void setStatus(String activityName, String status) {
    mMethodList.add(activityName + "." + status + "()");
    if (mStatusMap.containsKey(activityName)) mStatusMap.remove(activityName);
    mStatusMap.put(activityName, status);
  }

只需要每次把Activity的名字和它对应的状态作为参数放进去就好。

好了,现在让我们看看示例是如何用这个相同的示例进行UI内容的更新的吧。也就是工具类B,我们先看看代码:

public class Utils {

  private static StatusTracker mStatusTracker = StatusTracker.getInstance();

  /**
   * Helper method to print out the lifecycle state of each Activity.  Note this has
   * been wrapped in a Handler to delay the output due to overlaps in lifecycle state
   * changes as one Activity launches another.
   * @link http://developer.android.com/guide/topics/fundamentals/activities.html#CoordinatingActivities
   * @param viewMethods TextView to list out the lifecycle methods called
   * @param viewStatus TextView to list out the status of all Activity classes
   */
  public static void printStatus(final TextView viewMethods, final TextView viewStatus) {
      Handler handler = new Handler();
      handler.postDelayed(new Runnable() {
        public void run() {
          // Get the stack of Activity lifecycle methods called and print to TextView
          StringBuilder sbMethods = new StringBuilder();
          List<String> listMethods = mStatusTracker.getMethodList();
          for (String method : listMethods) {
              sbMethods.insert(0, method + "\r\n");
          }
          if(viewMethods != null) {
              viewMethods.setText(sbMethods.toString());
          }

          // Get the status of all Activity classes and print to TextView
          StringBuilder sbStatus = new StringBuilder();
          for (String key : mStatusTracker.keySet()) {
            sbStatus.insert(0,key + ": " + mStatusTracker.getStatus(key) + "\n");
          }
          if(viewStatus != null) {
              viewStatus.setText(sbStatus.toString());
          }
        }
      }, 750);
    }
}

我们看到它只有一个成员变量,一个方法。

成员变量是和所有Activity相同的变量,这样保证数据的一致性。方法只有打印打印状态信息的方法,接受两个TextView参数,这两个参数分别是贴图中的两个TextView。

可以看到 Utils 类的方法是通过Handle来更新UI的,内容比较简单就不说了。

好了这是代码部分,最后贴一下ActivityA的内容,B,C代码基本一致,只是少了onDestroy()方法里面clear()函数的调用,因为A先启动,结束的时候肯定也是A最后销毁,在Destroy的时候我们应该释放最后没有释放的资源,这里是清理,而其他的时候应该保留。

public class ActivityA extends Activity {

    private String mActivityName;
    private TextView mStatusView;
    private TextView mStatusAllView;
    private StatusTracker mStatusTracker = StatusTracker.getInstance();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_a);
        mActivityName = getString(R.string.activity_a);
        mStatusView = (TextView)findViewById(R.id.status_view_a);
        mStatusAllView = (TextView)findViewById(R.id.status_view_all_a);
        mStatusTracker.setStatus(mActivityName, getString(R.string.on_create));
        Utils.printStatus(mStatusView, mStatusAllView);
    }

    @Override
    protected void onStart() {
        super.onStart();
        mStatusTracker.setStatus(mActivityName, getString(R.string.on_start));
        Utils.printStatus(mStatusView, mStatusAllView);
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        mStatusTracker.setStatus(mActivityName, getString(R.string.on_restart));
        Utils.printStatus(mStatusView, mStatusAllView);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mStatusTracker.setStatus(mActivityName, getString(R.string.on_resume));
        Utils.printStatus(mStatusView, mStatusAllView);
    }

    @Override
    protected void onPause() {
        super.onPause();
        mStatusTracker.setStatus(mActivityName, getString(R.string.on_pause));
        Utils.printStatus(mStatusView, mStatusAllView);
    }

    @Override
    protected void onStop() {
        super.onStop();
        mStatusTracker.setStatus(mActivityName, getString(R.string.on_stop));
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mStatusTracker.setStatus(mActivityName, getString(R.string.on_destroy));
        mStatusTracker.clear();
    }

    public void startDialog(View v) {
        Intent intent = new Intent(ActivityA.this, DialogActivity.class);
        startActivity(intent);
    }

    public void startActivityB(View v) {
        Intent intent = new Intent(ActivityA.this, ActivityB.class);
        startActivity(intent);
    }

    public void startActivityC(View v) {
        Intent intent = new Intent(ActivityA.this, ActivityC.class);
        startActivity(intent);
    }

    public void finishActivityA(View v) {
        ActivityA.this.finish();
    }

}

这就是代码部分了。

在XML布局文件里我可看了看,这里简单贴一下代码

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        >
        <Button
            android:id="@+id/btn_start_b"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:text="@string/btn_start_b_label"
            android:onClick="startActivityB"
            />

        <Button
            android:id="@+id/btn_start_c"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:text="@string/btn_start_c_label"
            android:layout_toRightOf="@id/btn_start_b"
            android:onClick="startActivityC"
            />

        <Button
            android:id="@+id/btn_finish_a"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:text="@string/btn_finish_a_label"
            android:layout_toRightOf="@id/btn_start_c"
            android:onClick="finishActivityA"
            />

        <Button
            android:id="@+id/btn_start_dialog"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:text="@string/btn_start_dialog_label"
            android:layout_toRightOf="@id/btn_finish_a"
            android:onClick="startDialog"
            />

    </RelativeLayout>

变量的命名规范,还有layout_toRightOf,这个方法我都没怎么用,以前一直都用的绝对大小,学习一下。

还有我在TextView里面看到了,这个属性 android:typeface=”monospace”,我之前没怎么见过,就搜了一下,找到了这么个说法。

问:

  • How to change the font on the TextView? How to change the font in a TextView, as default it’s shown up as Arial? How to change it to Helvetica?

答:

  • First, the default is not Arial. The default is Droid Sans.
    Second, to change to a different built-in font, use android:typeface in layout XML or setTypeface() in Java.
    Third, there is no Helvetica font in Android. The built-in choices are Droid Sans (sans), Droid Sans Mono (monospace), and Droid Serif (serif). While you can bundle your own fonts with your application and use them via setTypeface(), bear in mind that font files are big and, in some cases, require licensing agreements

原来这是改变字体的属性。。(⊙o⊙)…还能改字体

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:15213次
    • 积分:663
    • 等级:
    • 排名:千里之外
    • 原创:52篇
    • 转载:1篇
    • 译文:1篇
    • 评论:4条
    最新评论