1、Activity活动
活动是一种可以包含用户界面的组件,主要用于和用户进行交互。
创建活动时需要注意是否勾选Generate Layout File
和Launcher Activity
。
项目中任何活动都应该重写onCreate
方法
-
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); }
-
setContentView()
方法给当前的活动加载布局,可传入一个布局文件的id。
2、Manifest文件
AndroidManifest文件中注册:
-
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.activitylifecycletest"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity" android:label="This is MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
-
<action android:name="android.intent.action.MAIN"/>
和<category android:name="android.intent.category.LAUNCHER"/>
用于配置主活动。 -
android:label
不仅会成为标题栏中的内容,还会成为启动器中应用程序显示的名称。
3、Toast消息窗
Toast是安卓提供的很好的提醒方式,可以将短小的信息通知给用户。
-
Toast.makeText(this, "message", Toast.LENGTH_SHORT).show();
-
第一个参数为context,即Toast的上下文,可传入活动作为context对象;第二个参数为显示内容;第三个参数为显示时间。
4、Menu菜单
Menu能在标题栏中提供菜单选项
-
res目录下新建Directory,命名为menu
-
在menu文件夹下新建XML文件,添加如下代码:
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/add_item" android:title="Add" /> <item android:id="@+id/remove_item" android:title="Remove" /> </menu>
-
在活动代码中重写
onCreateOptionsMenu()
方法:@Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; }
getMenuInflater
方法能得到MenuInflater对象,再调用inflater
方法可以给当前活动创建菜单。 -
在活动中重写
onOptionItemSelected
方法,定义菜单响应事件:public boolean onOptionsItemSelected(@NonNull MenuItem item) { switch (item.getItemId()) { case R.id.add_item: { Toast.makeText(this, "You clicked Add", Toast.LENGTH_SHORT).show(); break; } case R.id.remove_item: { Toast.makeText(this, "You clicked Remove", Toast.LENGTH_SHORT).show(); break; } default: break; } return true; }
销毁活动:finish()
方法
5、Intent活动跳转
Intent的两种实现方式:
-
显式Intent:
Intent(Context packageContext,Class<?>cls)
。Intent构建后运行startActivity
启动活动。button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(FirstActivity.this, SecondActivity.class); startActivity(intent); } });
-
隐式Intent:指定了一系列抽象的
action
和category
在
<activity>
下配置<intent-filter>
:<activity android:name=".SecondActivity"> <intent-filter> <action android:name="com.example.activityTest.ACTION_START"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </activity>
category标签包含了一些附加信息,更精确地指明当前的活动能够响应的Intent中可能带有的category。
只有action和category中内容能够同时匹配Intent中的action和category时,该活动才能响应该Intent。
活动中的隐式Intent写法:
Intent intent=new Intent("com.example.activityTest.ACTION_START");
一个Intent只能有一个action,但是可以指定多个category,通过下列方式增加category:
intent.addCategory("com.example.activityTest.MY_CATEGORY");
同时,在Manifest文件中应该添加category的声明:
<category android:name="com.example.activityTest.MY_CATEGORY">
隐式Intent不仅可以启动自己程序内的活动,也可以启动其他程序的活动,以浏览器为例:
-
Activity中添加:
Intent intent =new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse("http://www.baidu.com"));
Intent.ACTION_VIEW
是安卓系统内置的动作,其值为android.intent.action.view
。Uri.parse
将网址解析成Uri对象,再调用Intent的setData方法把Uri对象传递进去。
-
Manifest中添加:
<action android:name="android.intent.action.VIEW"/>
-
<intent-filter>
中可添加<data>
标签,用于更精确地指定当前活动能够响应什么类型的数据android:scheme 指定数据的协议 android:host 指定数据的主机名部分 android:port 指定数据的端口部分 android:path 指定主机名和端口之后的部分 android:mimeType 指定可以处理的数据类型,允许使用通配符的方式指定
只有
<data>
标签中指定的内容与Intent中携带的Data完全一致时,才能响应该Intent。
5.1、向下一个活动传递数据
Intent中提供了一系列putExtra()
方法的重载,可将数据暂存在Intent中,跳转到下一个活动中可从中提取出:
-
本活动中传数据:
intent.putExtra("key", value); // "key"为数据的键,value为数据的值
-
下一个活动中提取数据:
Intent intent=getIntent(); String str=intent.getStringExtra("key"); // getIntExtra, getBooleanExtra...
5.2、向上一个活动返回数据
Activity中startActivityForResult()
可用于启动活动,并在活动销毁时将一个结果返回给上一个活动。
srartActivityForResult
方法接收两个参数,第一个参数为Intent,第二个参数为请求码,用于之后的回调中判断数据的来源。
本活动中设置跳转动作:
startActivityForResult(intent, 1);
下一个活动中需要设置返回的结果:
intent.putExtra("return", value);
setResult(RESULT_OK, intent); // RESULT_OK或RESULT_CANCELED
finish();
本活动中需要重写回调的onActivityResult
方法:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
switch(requestCode){
case 1:
if(resultCode==RESULT_OK){
...
}
break;
default:
break;
}
}
// 首先检查requestCode判断数据来源,再检查resultCode判断数据处理是否成功
如果想要用户点击返回键而不是特定按钮返回上一个活动,则需要在下一个活动中重写onBackPressed
方法:
@Override
public void onBackPressed(){
Intent intent =new Intent();
intent.putExtra("return", value);
setResult(RESULT_OK, intent);
finish();s
}
6、活动的生命周期
返回栈,一个任务就是一组存放在栈里的活动的集合。
生命周期的四个状态:
- 运行:活动位于返回栈的栈顶
- 暂停:活动不处于栈顶,但仍然可见
- 停止:活动不处于栈顶,且完全不可见
- 销毁:活动从栈中移除
Activity的7个回调方法:
onCreate
:活动创建的时候调用onStart
:活动由不可见变为可见时调用onResume
:活动准备好与用户进行交互时调用onPause
:启动或回复另一个活动时调用onStop
:活动完全不可见时调用onDestroy
:活动销毁前调用onRestart
:活动由停止转为运行前调用
3个生存期:
- 完整生存期:onCreate()~onDestroy()
- 可见生存期:onStart()~onStop()
- 前台生存期:onResume()~onPause()
避免因活动被回收导致关键数据丢失:onSaveInstanceState()
-
重写
onSaveInstanceState
方法@Override protected void onSaveInstanceState(Bundle outState){ super.onSaveInstanceState(outState); String value="value"; outState.putString("key",calue); }
-
修改
onCreate
方法if(savedInstanceState!=null){ String value=savedInstanceState.getString("key"); // getString, getInt... ... }
Intent可以结合Bundle一起用于传递数据。将需要传递的数保存在Bundle对象中,然后将Bundle对象存放在Intent内;在目标活动中先从Intent中取出Bundle,再从Bundle中取出数据。
7、活动的启动模式
实际项目中应该为每个活动指定恰当的启动模式。
在Manifest文件中通过给<activity>
指定android:launchMode
选择启动模式。
启动模式有4种:
- standard:活动的默认启动模式。每当启动一个新的活动,它就会在返回栈内入栈,并位于栈顶。每次启动都会创建该活动的一个实例(无论栈中是否已经有此活动)。
- singleTop:在启动活动的时候如果返回栈的栈顶已经是该活动,则可以直接使用它,不会再创建新的活动实例。如果活动实例不在栈顶,则仍然会创建新的实例。
- singleTask:创建实例之前,会检查返回栈的元素。如果返回栈中存在该活动的实例,则直接使用该实例并把这个活动之上的所有活动全部出栈;如果不存在则创建新的实例。
- singleInstance:此模式的活动会启用一个新的返回栈来管理这个活动。此模式可解决不同应用程序共享活动实例的问题。
8、活动的设计技巧
知晓是当前是哪个活动:
-
新建BaseActivity类:不同于新建一个活动,只新建一个Java类继承于
AppcompatActivity
,并重写onCreate
方法:protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); Log.d("BaseActivity", getClass().getSimpleName()); }
-
其他的活动继承于BaseActivity类:当新建一个活动实例时日志会打印这个活动的名称。
随时随地退出程序:
-
新建一个ActivityCollector类作为活动管理器:
public class ActivityCollector{ public static List<Activity> activities=new ArrayList<>(); public static void addActivity(Activity activity){ activities.add(activity); } public static void removeActivity(Activity activity){ activities.remove(activity); } public static void finnishAll(){ for(Activity activity:activities){ if(!activity.isFinishing){ activity.finish(); } } } }
-
(可选)在销毁所有活动的代码后加上杀掉当前进程的代码:
android.os.Process.killProcess(android.os.Process.myPid());
启动活动的最佳写法:
-
编写actionStart()方法:
public static void actionStart(Context context,String data1,String data2){ Intent intent=new Intent(context,MyActivity.class); intent.putExtra("param1",data1); intent.putExtra("param2",data2); context.startActivity(intent); }
-
好处:下一个活动所需参数全部体现,方便对接;简化代码。