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

原创 2016年08月30日 09:55:20

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⊙)…还能改字体

版权声明:本文为博主原创文章,未经博主允许不得转载。

谷歌官方Android应用架构库——处理生命周期

谷歌官方Android应用架构库——处理生命周期
  • hubinqiang
  • hubinqiang
  • 2017年06月11日 05:04
  • 2299

android 之 Activity lifecycle

当页面加载一个新的Activity 时会调用默认实现的三个方法,依次为: onCreate();onStart();onResume(); 当这三个方法被依次运行完以后,该Activity 就可以...
  • liuc0317
  • liuc0317
  • 2011年09月20日 09:04
  • 5987

【Android】 Activity Lifecycle

前言 之前面试过程中,被问到过
  • u010119170
  • u010119170
  • 2014年05月15日 18:34
  • 1238

阅读Android官方教程 Google Training 1.3 ----- Manage the Activity Lifecycle

阅读谷歌官方教程第一章 Getting Started这次官方的内容竟然是中文的,但是内容涉及到了Activity的生命周期的管理,看完感觉内容很丰满,学到了很多东西啊。看完这节教程,觉得原来自己开发...
  • Bingtang_blog
  • Bingtang_blog
  • 2016年08月29日 12:23
  • 299

工作流学习——Activiti流程实例、任务管理四步曲

我们这篇文章主要是流程实例、执行对象、任务以及他们之间的关系进行了学习,同时我们还将启动和查询流程实例、判断流程实例是否执行结束、查看和办理任务以及查询历史任务都进行了介绍。...
  • zwk626542417
  • zwk626542417
  • 2015年06月26日 10:15
  • 54915

Android官方架构组件介绍之LifeCycle

下面是官方提供的Android App开发的架构图: 从上图可以看到一些关键字:ViewModel,LiveData,Room等。其实看了上面视频的会发现Google官方Android架...
  • g6uqwseseo
  • g6uqwseseo
  • 2017年05月22日 09:32
  • 7300

ActivityLifeCycle官方demo解析

1.关于Activity的生命周期的几篇文章: http://1.duoinfo.sinaapp.com/?p=330 http://1.duoinfo.sinaapp.com/?p=332 ...
  • chenfuduo_loveit
  • chenfuduo_loveit
  • 2015年03月14日 09:19
  • 988

Lifecycle Sorter插件

可以根据Activity或者fragment的生命周期对其生命周期方法位置进行先后排序,快捷键Ctrl + alt + K 参考:http://www.open-open.com/lib/view/...
  • amoscxy
  • amoscxy
  • 2017年01月02日 17:04
  • 891

Android应用程序四大组件之Activity(二)

Activity状态保存 1.onSaveInstanceState()/onCreate()/onRestoreInstanceState() 系统在回收当期Activity之前会调用onSav...
  • ajq1989
  • ajq1989
  • 2011年09月05日 23:15
  • 866

Google I/O Android官方新体系架构之:Lifecycle

Google I/O 2017 Android官方新体系架构之:LifecycleGoogle官方在2017 I/O大会中引入一些列Android新的体系架构内容,其中有一个是Android的Life...
  • zhangphil
  • zhangphil
  • 2017年08月10日 14:06
  • 3553
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:关于Google 教程中 Manage the Activity Lifecycle 示例的学习
举报原因:
原因补充:

(最多只允许输入30个字)