第二章-探究活动

布局

  1. android:id="@+id/button_1"

给当前的元素定义一个唯一标识符。

  1. android:layout_width="match_parent"

指定当前元素的宽度,match_parent表示让当前元素和父元素一样宽。

  1. android:layout_height="wrap_content"

指定当前元素的高度,wrap_content表示当前元素的高度只要能刚好包含里面的内容就行。

  1. android:text="Button 1"

指定了元素中显示的文字内容。

  1. setContentView(R.layout.first_layout);

这里调用了setContentView()方法来给当前的活动加载一个布局,在括号中传入一个布局文件的id。项目中添加的任何资源都会在R文件中生成一个相应的资源id。

在AndroidMainfest文件中注册活动

所有活动都要在AndroidMainfest.xml中进行注册才能生效。

  1. <application
  2. android:allowBackup="true"
  3. android:icon="@mipmap/ic_launcher"
  4. android:label="@string/app_name"
  5. android:roundIcon="@mipmap/ic_launcher_round"
  6. android:supportsRtl="true"
  7. android:theme="@style/Theme.ActivityTest">
  8. <activity android:name=".FirstActivity"></activity>
  9. </application>

studio自动生成,完成了activity的注册,但是光有注册程序是不能运行起来的。

  1. <application
  2. android:allowBackup="true"
  3. android:icon="@mipmap/ic_launcher"
  4. android:label="@string/app_name"
  5. android:roundIcon="@mipmap/ic_launcher_round"
  6. android:supportsRtl="true"
  7. android:theme="@style/Theme.ActivityTest">
  8. <activity android:name=".FirstActivity"
  9. android:label="This is FirstActivity">
  10. <intent-filter>
  11. <action android:name="android.intent.action.MAIN"/>
  12. <category android:name="android.intent.category.LAUNCHER"/>
  13. </intent-filter>
  14. </activity>
  15. </application>

对比studio自动生成的xml文件,在标签中添加了标签,并且在标签内添加了
这两句声明。

android:label=”This is FirstActivity”:指定后动中标题栏的内容。

  1. **注意:给主活动指定的label不仅会称为标题栏中的内容,还会成为启动器中应用程序显示的名称。**

如果应用程序中没有声明主活动,程序可以安装,但是无法在启动器中看到或者打开这个程序,这个程序一般都是作为第三方服务提供其他应用在内部进行调用,比如支付宝快捷支付。

在活动中使用Toast

Toast是Android系统提供的提醒方式。

在程序中使用Toast将一些短小的信息通知给用户,这些信息在一段时间后自动消失,并且不会占用任何屏幕空间。

  1. Button button1 = (Button) findViewById(R.id.button_1);

findViewById():获取在布局文件中定义的元素。返回的是一个View对象。

  1. button1.setOnClickListener()

得到按钮的失利后,调用setOnClickListener()方法为按钮注册一个监听器,点击按钮时会执行监听器中的onClick()方法。

因此,弹出Toast的功能写在onClick()方法中。


Android事件与事件监听器:

事件监听器种类:

1、单击事件(View.OnClickListener):当用户触碰到某个组件或者方向键被按下时产生该事件,该事件的处理方法是onClick()。

2、焦点事件(View.OnFocusChangeListener):组件得到或者失去焦点时产生该事件,事件处理方法是onFocusChange()。

3、按键事件(View.OnKey Listener):用户按下或者释放设备上的某个按键时产生,事件处理方法是 onKey()。

4、触碰事件(View.OnTouchListener):设备具有触摸屏功能时,触碰屏幕产生该事件。事件处理方法是onTouch()。

5、创建上下文菜单事件(View.OnCreateContextMenu Listener):创建上下文菜单时产生该事件,事件处理方法是 onCreateContextMenu()。

事件处理步骤:

  1. 1、创建事件监听器。
  2. 2、给要响应事件的组件注册事件监昕器。
  3. 3、在事件处理方法中编写实现代码。

demo:

  1. button1.setOnClickListener(new View.OnClickListener() {
  2. @Override
  3. public void onClick(View v) {
  4. Toast.makeText(FirstActivity.this,"你按下了按钮1",Toast.LENGTH_SHORT).show();
  5. }
  6. });

Toast用法

  1. 通过静态方法makeText()创建出一个Toast对象。
    注意:makeText需要传入三个参数
    参数1:Context:Toast要求的上下文。
    参数2:Toast显示的文本内容。
    参数3:Toast显示的时长。
  2. 调用show()方法,将Toast显示出来。

在活动中使用Menu

  1. 创建资源文件:在res目录下新建menu目录,再在menu目录中创建main菜单文件。
  2. 编写main.xml文件
    标签:创建具体的某一个菜单项。

    1. <item
    2. android:id="@+id/add_item"
    3. android:title="Add"/>
    4. <item
    5. android:id="@+id/remove_item"
    6. android:title="Remove"/>
  3. 在活动中重写onCreatOptionMenu()方法

    1. public boolean onCreateOptionsMenu(Menu menu) {
    2. getMenuInflater().inflate(R.menu.main,menu);
    3. return true;
    4. }
    • getMenuInflater():得到MenuInflater对象。
    • inflate():给当前活动创建菜单。
      • 参数1:指定通过哪一个资源文件创建菜单。
      • 参数2:指定菜单项将添加到哪一个Menu对象当中。
    • true:true表示允许创建的菜单显示出来,如果返回false,创建的菜单将无法显示。
  1. 在活动中重写onOprionsItemSelected()方法(定义菜单响应事件)
    调用item.getItemId()判断点击的是哪一个菜单项,然后给每个菜单项加入自己的逻辑处理。
    第一步是创建菜单的资源文件,在文件中要写出菜单项,给菜单项指定标识符,接着回到活动中重写创建菜单的方法,然后再给菜单写响应事件,这里通过菜单项的标识符来获取菜单项。
    1. public boolean onOptionsItemSelected(@NonNull MenuItem item) {
    2. switch (item.getItemId()){
    3. case R.id.add_item:
    4. Toast.makeText(this,"You clicked Add",Toast.LENGTH_SHORT).show();
    5. break;
    6. case R.id.remove_item:
    7. Toast.makeText(this,"You clicked Remove",Toast.LENGTH_SHORT).show();
    8. break;
    9. default:
    10. }
    11. return true;
    12. }

    Menu用法总结:

使用Intent在活动之间穿梭

Intent是Android程序中各组件之间进行交互的一种重要方式,Intent不仅可以指明当前组件想要执行的动作,还可以在不同组件之间传递数据。

Intent一般可被用于启动活动、启动服务以及发送广播等场景。

显示Intent

Intent(Context packageContext,Class<?>cls)

  • 参数1:提供一个启动活动的上下文。
  • 参数2:指定想要启动的目标活动。
  1. Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
  2. startActivity(intent);

代码分析:在FirsActivity这个活动的基础上打开SecondActivity这个活动。

隐式Intent

隐式Intent并不明确指出我们想要启动哪一个活动,而是指定了一系列更为抽象的action和category等信息,然后交由系统去分析这个Intent,并帮我们找出合适的活动去启动。

  1. <activity android:name=".SecondActivity"
  2. android:label="This is SecondActivity">
  3. <intent-filter>
  4. <action android:name="com.example.activitytest.ACTION_START"/>
  5. <category android:name="android.intent.category.DEFAULT"/>
  6. </intent-filter>
  7. </activity>

:指明当前活动可以响应的aciton。

:更精确地指明了当前的活动能够响应的Intent中还可能带有的category。

只有中的内容能够同时匹配上Intent中指定的action和category时,这个活动才能响应该Intent。

  1. public void onClick(View v) {
  2. Intent intent = new Intent("com.example.activitytest.ACTION_START");
  3. startActivity(intent);
  4. }
  5. });
  1. Intent intent = new Intent("com.example.activitytest.ACTION_START");

将action的字符串传入Intent的构造函数,表明当前活动想要启动的能够响应该字符串的活动。

  1. android.intent.category.DEFAULT

这是一种默认的category,在调用startActivity()方法的时候会自动将这个category添加到Intent中。

每个Intent中只能指定一个action,但却能指定多个category。

例:

  1. <intent-filter>
  2. <action android:name="com.example.activitytest.ACTION_START"/>
  3. <category android:name="android.intent.category.DEFAULT"/>
  4. <category android:name="android.intent.category.MY_CATEGORY"/>
  5. </intent-filter>
  1. public void onClick(View v) {
  2. Intent intent = new Intent("com.example.activitytest.ACTION_START");
  3. intent.addCategory("android.intent.category.MY_CATEGORY");
  4. startActivity(intent);
  5. }
  6. });

Intent用法总结:

显示Intent:

  • 第一步:在要接收响应请求的活动中构建关于发起响应请求的活动的Intent。
  • 第二步:调用startActivity()方法执行构建好的Intent

隐式Intent:

  • 第一步:在AndroidManifest.xml文件中接收响应请求的活动中配置和标签。
  • 第二步:在发起响应请求的活动中构造Intent和执行。

通过隐式Intent启动其他程序

  1. Intent intent = new Intent(参数1);
  2. intent.setData(Uri.parse(参数2));
  3. startActivity(intent);
  • 参数1:设置动作
  • 参数2:设置协议

向下一个活动传递数据

思想:把数据进行暂存,然后再取出来。

  • 步骤1:把数据暂存:

    1. String data = "Hello SecondActivity";
    2. Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
    3. intent.putExtra("extra_data",data);
    4. startActivity(intent);
  • 步骤2:取数据:

    1. Intent intent = getIntent();
    2. String extra_data = intent.getStringExtra("extra_data");
    3. Log.d("SecondActivity",extra_data);

这里给数据命名为extra_data,然后把名字作为键,存和取都通过键来操作。需要注意的地方是当数据的类型发生改变时,存数据和取数据时需要注意变量类型。

返回数据给上一个活动

  1. public void onClick(View v) {
  2. Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
  3. startActivityForResult(intent,1);
  4. }

startActivityForResult(intent,1):第二个参数是请求码,用于在之后的回调中判断数据的来源。

  1. public void onClick(View v) {
  2. Intent intent = new Intent();
  3. intent.putExtra("data_return","Hello FirstActivity");
  4. setResult(RESULT_OK,intent);
  5. finish();
  6. }

setResult(RESULT_OK,intent):专门用于向上一个活动返回数据。

第一个参数用于向上一个活动返回处理结果。

第二个参数把带有数据的Intent传递回去。

注意:使用startActivityForResult()方法启动活动的,在活动被销毁之后会回调上一个活动的onActivityResult()方法,因此需要在上一个方法中重写onActivityResult()方法。

  1. protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  2. super.onActivityResult(requestCode, resultCode, data);
  3. switch (requestCode) {
  4. case 1:
  5. if (resultCode == RESULT_OK) {
  6. String returnData = data.getStringExtra("data_return");
  7. Log.d("FirstActivity", returnData);
  8. }
  9. break;
  10. default:
  11. }
  12. }
  • 参数1:启动活动时传入的请求码。
  • 参数2:返回数据时传入的处理结果。
  • 参数3:携带着返回数据的Intent。

活动的生命周期

Android使用任务(Task)来管理活动。

一个任务就是一组存放在栈里的活动的集合,这个栈也被称作返回栈(Back Stack)。

活动的生存期

七个回调方法:

  • onCreate():在活动第一次被创建时调用,在这个方法中完成活动的初始化。
  • onStart():在活动由不可见变为可见的时候调用。
  • onResume():在活动准备好和用户进行交互的时候调用。此时的活动一定位于返回栈的栈顶,并且处于运行状态。
  • onPause():在系统准备去启动或者恢复另一个活动的时候调用。通常会在这个方法中将一些消耗CPU的资源释放掉,以及保存一些关键数据。
  • onStop():在活动完全不可见的时候调用。它和onPause()方法的主要区别在于,如果启动的新活动是一个对话框的活动,那么onPause()方法会得到执行,而onStop()方法并不会执行。
  • onDestroy():在活动被销毁时调用,之后的状态将变为销毁状态。
  • onRestart():在活动由停止状态变为运行状态之前调用,也就是活动被重新启动了。

活动的三种生存期:

  • 完整生存期:活动在onCreate()方法和onDestroy()方法之间所经历的就说完整生存期。
  • 可见生存期:活动在OnStart()方法和onStop()方法之间所经历的。在可见生存期内,活动对于用户总是可见的,即便有可能无法和用户进行交互,我们可以通过这两个方法,合理地管理那些对用户可见的资源。
  • 前台生存期:活动在onResume()方法和onPause()方法之间所经历的就说前台生存期。在前台生存期内,活动总是处于运行状态的,此时的活动是可以和用户进行交互的。

活动生命周期图:

第二章-探究活动 - 图1

活动被收回事数据的处理

通过onSaveInstanceState()来进行存取,和Intent基本一样。

核心思想是键值对。

活动的启动模式

四种启动模式:standard,singleTop,singleTask,singleInstance

standard

活动默认的启动模式,在不进行显示指定的情况下,所有活动都会自动使用此启动模式。

在standard模式下,每当启动一个新的活动,它就会在返回栈中入栈,并处于栈顶的位置。

singleTop

当活动的启动模式指定为singleTop,在启动活动时如果发现返回栈的栈顶已经是该活动,则认为可以直接使用它,不会再创建新的活动实例。

singleTask

当活动的启动模式指定为singleTask,每次启动该活动系统时系统首先会在返回栈中检查是否存在该活动的实例,如果发现已经存在则直接使用该实例,并把这个活动之上的所有轰动统统出栈,如果没有发现就会创建一个新的活动实例。

singleInstance

每一个应用程序都有自己的返回栈。

指定为singleInstance模式的活动会启用一个新的返回栈来管理这个活动。这样做的目的是不管哪个应用程序来访问这个活动,都共用的同一个返回栈。

活动的最佳实践

如何知道当前界面是哪一个活动

在活动和父类之间建立一个类,使其为父类的子类,活动的父类。然后再在这个类中写一个日志打印处于运行中状态的活动的名字。,当子类的活动每次处于运行中状态时,日志就会被打印。

随时随地退出程序

新建一个专门的集合类对所有的活动进行管理,这个类向活动类提供对所有活动进行管理的方法。比如新增一个活动,删除一个活动,删除所有活动。

启动活动的最佳写法

添加启动方法,在启动方法中写明启动活动所需要的数据参数。