1、Activity初步认识:【建立、配置、启动Activity】android
(一)、建立Activity:浏览器
建立Activity:继承于Activity或其子类,重写onCreate()方法。bash
(二)、Activity的注册配置:app
做为四大组件之一的Activity,必需要在AndroidManifest清单文件中进行注册。若是没有配置,而又在程序中启动了该Activity,将抛出异常(ActivityNotFoundException)。ide
注册配置的核心代码:ui
<application
android:allowBackup=*"true"*
android:icon=*"@drawable/ic_launcher"*
android:label=*"@string/app_name"*
android:theme=*"@style/AppTheme"*>
<activity
android:name=*".MainActivity"*
android:label=*"@string/app_name"*>
<intent-filter>
<actionandroid:name=*"android.intent.action.MAIN"* />
<categoryandroid:name=*"android.intent.category.LAUNCHER"*/>
</intent-filter>
</activity>
<activity
android:name=*".HeadpicActivity"*
android:label=*"@string/title_activity_headpic"* >
</activity>
</application>
复制代码
当在AndroidManifest清单文件中,设置多个页面都是默认启动页,不会报错,会由上向下以第一个配置的LAUNCHER 去运行!this
当在AndroidManifest清单文件中,若是不设置默认启动页,程序运行不了spa
(三)、启动Activity:code
(四)、Activity之间交换数据:cdn
第一种方式:
第二种方式:【经常使用】
甲页面利用bundle对象来保存全部须要传递的数值,经过intent的putExtras()方法传值,乙页面利用intent对象的getExtras()方法返回bundle对象,将全部接收的数据放在bundle对象中,利用bundle的get系列方法一一去除数据。
【备注:】若是甲页面使用putExtras()方法传值,则乙页面使用getExtras()接收值。若是甲页面使用putExtra()方法传值bundle而且传入bundle是有key值得,则乙页面要使用getBundleExtra()方法接收值,拿到bundle
Activity之间是否能够传递对象呢?【掌握Serializable的用法】
一、传递通常数据的核心代码:
(1)、MainActivity页面:
public void clickButton(View view) {
switch (view.getId()) {
case R.id.button_main_tonext:
Intent intent = new Intent(MainActivity.this,NextActivity.class);
Bundle bundle = new Bundle();
bundle.putString("myname", "lgc");
bundle.putInt("age", 16);
intent.putExtras(bundle);
startActivity(intent);
break;
}
}
复制代码
(2)、NextActivity页面:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_next);
// 接收第一个页面的传值
Intent intent = getIntent();
Bundle bundle = intent.getExtras();
String name = bundle.getString("myname");
int age = bundle.getInt("age");
this.setTitle(name + ":" + age);
}
复制代码
2、Activity——调用另外一个Activity并返回结果:
(一)、概念:
甲页面调用乙页面,当用户在乙页面完成任务后,程序自动返回到甲页面,而甲页面必须可以获取到用户在完成乙页面后传递的数据结果。
(二)、作法:
与普通的页面交换数据不一样的是,要使用startActivityForResult()方法来启动另外一个Activity。
(三)、示例代码:
一、MainActivity页面:
public class MainActivity extend Activity {
private ImageView imageView_main_headpic;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView_main_headpic = (ImageView) findViewById(R.id.imageView_main_headpic);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true ;
}
public void clickButton(View view) {
switch (view.getId()) {
case R.id.button_main_selectpic:
Intent intent = new Intent(MainActivity.this, HeadpicActivity.class);
startActivityForResult(intent, 0);
break;
}
}
@Override
protected void onActivityResult( int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 0 && resultCode == 1) {
Bundle bundle = data.getExtras();
int imgid = bundle.getInt("imgId");
imageView_main_headpic.setImageResource(imgid);
}
}
}
复制代码
二、NextActivity页面:
public class HeadpicActivity extends Activity {
private GridView gridView_headpic_show;
// 定义数据源
private int [] imgIds = new int [] { R.drawable.img01, R.drawable.img02,
R.drawable.img03, R.drawable.img04, R.drawable.img05,
R.drawable.img06, R.drawable.img07, R.drawable.img08,
R.drawable.img09 };
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_headpic);
gridView_headpic_show = (GridView) findViewById(R.id.gridView_headpic_show);
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
for(int i = 0; i < imgIds.length; i++) {
Map<String, Object> map = **new** HashMap<String, Object>();
map.put("headpic", imgIds[i]);
map.put("picname", "头像—" + i);
list.add(map);
}
SimpleAdapter adapter = new SimpleAdapter(this, list,
R.layout.item_gridview_headpic, new String[] { "picname",
"headpic" }, new int[] {
R.id.text_item_gridview_picname,
R.id.imageView_item_gridview_headpic });
gridView_headpic_show.setAdapter(adapter);
gridView_headpic_show.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Intent intent = getIntent();
Bundle bundle = new Bundle();
bundle.putInt("imgId", imgIds[position]);
intent.putExtras(bundle);
setResult(1, intent);
finish();
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.headpic, menu);
return true;
}
复制代码
3、Activity生命周期:
(一)、引入:人的生命周期是怎么样的?
(二)、Activity生命周期:
一、Activity一辈子中有七种不一样的状态。
【备注:】
A、七个生命周期组合:
B、七个生命周期按阶段划分:
二、定义生命周期的做用:
三、生命周期的金字塔图
(三)、实例代码操做:
04-23 03:51:29.750: I/MainActivity(741): ==MainActivity onCreate执行了
04-23 03:51:29.759: I/MainActivity(741): ==MainActivity onStart执行了
04-23 03:51:29.759: I/MainActivity(741): ==MainActivity onResume执行了
04-23 03:52:04.780: I/MainActivity(741): ==MainActivity onPause执行了
04-23 03:52:04.791: I/MainActivity(741): ==MainActivity onStop执行了
04-23 03:52:04.791: I/MainActivity(741): ==MainActivity onDestroy执行了
切换横屏:
04-23 03:51:29.750: I/MainActivity(741): ==MainActivity onCreate执行了
04-23 03:51:29.759: I/MainActivity(741): ==MainActivity onStart执行了
04-23 03:51:29.759: I/MainActivity(741): ==MainActivity onResume执行了
04-23 03:52:04.780: I/MainActivity(741): ==MainActivity onPause执行了
04-23 03:52:04.791: I/MainActivity(741): ==MainActivity onStop执行了
04-23 03:52:04.791: I/MainActivity(741): ==MainActivity onDestroy执行了
04-23 03:51:29.750: I/MainActivity(741): ==MainActivity onCreate执行了
04-23 03:51:29.759: I/MainActivity(741): ==MainActivity onStart执行了
04-23 03:51:29.759: I/MainActivity(741): ==MainActivity onResume执行了
复制代码
【横竖屏切换时的生命周期问题的解决】
(一)、android:configChanges属性
对android:configChanges属性,通常认为有如下几点:
一、不设置Activity的android:configChanges时,切屏会从新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次
二、设置Activity的android:configChanges="orientation"时,切屏仍是会从新调用各个生命周期,切横、竖屏时只会执行一次
三、设置Activity的android:configChanges="orientation|keyboardHidden"时,切屏不会从新调用各个生命周期,只会执行onConfigurationChanged方法
可是,自从Android 3.2(API 13),在设置Activity的android:configChanges="orientation|keyboardHidden"后,仍是同样 会从新调用各个生命周期的。由于screen size也开始跟着设备的横竖切换而改变。因此,在AndroidManifest.xml里设置的MiniSdkVersion和 TargetSdkVersion属性大于等于13的状况下,若是你想阻止程序在运行时从新加载Activity,除了设置"orientation", 你还必须设置"ScreenSize"。
解决方法: AndroidManifest.xml中设置android:configChanges="orientation|screenSize“
4、任务与回退栈:
(一)、任务Task:
一、概念:
一个任务(task)就是在执行某项工做时与用户进行交互的Activity的集合。这些Activity按照被打开的顺序依次被安排在一个堆栈中(回退栈)。
二、主屏页面:
设备的主屏是大多数任务的启动位置,当用户触摸一个应用程序启动器图标(或者app快捷图标),应用程序的任务就会在前台显示。若是相关应用程序的任务不存在,那么就会有一个新的任务被建立,而且应用程序打开的“主”Activity会做为任务中的根Activity。
(二)、回退栈:
一、概念:
在当前的Activity启动了另外一个Activity时,这个新的Activity被放到了堆栈的顶部,而且带有焦点。前一个Activity并无消失,而是保存在回退栈中,此时它处于中止状态。
当用户按下回退按钮时,当前的Activity会被从回退栈的顶部弹出(这个Activity被销毁),而前一个Activity被恢复。堆栈中的Activity不会被从新排列。所以,回退栈的操做跟后进先出的对象结构是同样的。
在用户按下回退按钮时,当前Activity被销毁,而且前一个Activity被恢复。若是用户继续按回退按钮,那么回退栈中的每一个Activity会被依次弹出,前一个Activity会被显示,直到用户返回主屏(或者返回到任务开始时运行的那个Activity)。当全部的Activity从回退栈中被删除时,这个任务就再也不存在了。
图1:用一个时间表显示了当前回退堆栈中的Activity之间在每一个时间点的处理过程
二、多个任务:
图2. 两个任务:任务B在前台接受用户交互,而任务A则在后台等待被恢复。
【注意:】后台中能够同时拥有多个任务,可是若是用户同时运行了不少后台任务,系统为了回收内存可能销毁一些后台的Activity,从而致使Activity的状态丢失。
由于回退堆栈中的Activity未曾被从新排列,所以若是容许用户从多个Activity中启动一个特殊的Activity,那么就会建立一个新的Activity实例,而且在堆栈的顶部弹出(而不是把以前的Activity实例带到堆栈的顶端)。这样在你的应用程序中一个Activity就可能被实例化屡次(甚至来自不一样任务)。
复制代码
(三)、Activity和Task的默认行为的总结:
一、当Activity A启动Activity B时,ActivityA被终止,可是系统保留了它的状态(如滚动条的位置和录入表单的文本)。若是用户在Activity B中按回退按钮,Activity A会使用被保存的状态来进行恢复。
二、当用户经过按主页(Home)按钮离开一个任务时,当前的Activity会被终止,而且被放入后台。系统会保留任务中每一个Activity的状态。若是用户随后经过选择启动图标来恢复这个任务,那么任务会来到前台,而且恢复了堆栈顶部的Activity。
三、若是用户按下回退按钮,当前的Activity会从堆栈中被弹出而且被销毁。堆栈中的前一个Activity会被恢复。Activity被销毁时,系统不会保留Activity的状态。
四、Activity可以被实例化屡次,甚至来自其余任务。
5、Activity启动模式:
在Android中每一个界面都是一个Activity,切换界面操做实际上是多个不一样Activity之间的实例化操做。在Android中Activity的启动模式决定了Activity的启动运行方式。Android总Activity的启动模式分为四种:
复制代码
(一)、Activity启动模式设置:
<activity android:name=".MainActivity" android:launchMode="standard" />
复制代码
(二)、Activity的四种启动模式:
1. standard(备注:standard是系统默认的启动模式。)
标准启动模式,每次激活Activity时都会建立Activity,并放入任务栈中。每一个窗体的getTaskId()保持不变,可是this.hashCode()发生改变。
2. singleTop
若是在任务的栈顶正好存在该Activity的实例, 就重用该实例,而不会建立新的Activity对象,不过它会调用onNewIntent()方法。若是栈顶部不存在就会建立新的实例并放入栈顶(即便栈中已经存在该Activity实例,只要不在栈顶,都会建立实例)。会回调onNewIntent()方法。
3. singleTask
若是在栈中已经有该Activity的实例,就重用该实例(会调用实例的onNewIntent())。重用时,会让该实例回到栈顶,所以在它上面的实例将会被移除栈。若是栈中不存在该实例,将会建立新的实例放入栈中。
和singleTop在名字上便可看出区别,即singleTop每次只检测当前栈顶的Activity是不是咱们须要请求建立的,而singleTask则会检测栈中所有的Activity对象,从上向下,若是检测到是咱们所请求的则会消灭此Activity对象上面的对象,直接把检测到的咱们须要的Activity置为栈顶。
4. singleInstance
与singleTask模式的区别是存放singleInstance模式窗口对象的回退栈不能有其余任何窗口对象。所以若是该窗口不存在,则要新建任务来存放该singleInstance模式窗口。也就是说getTaskId()会发现任务id发生了变化。
此启动模式和咱们使用的浏览器工做原理相似,在多个程序中访问浏览器时,若是当前浏览器没有打开,则打开浏览器,不然会在当前打开的浏览器中访问。此模式会节省大量的系统资源,由于他能保证要请求的Activity对象在当前的栈中只存在一个。
复制代码
总之,在开发Android项目时,巧妙设置Activity的启动模式会节省系统开销和提升程序运行效率。
【备注:】
android:screenOrientation="portrait"
android:configChanges="keyboardHidden|orientation|screenSize"
一、不设置Activity的android:configChanges时,切屏会从新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次
二、设置Activity的android:configChanges="orientation"时,切屏仍是会从新调用各个生命周期,切横、竖屏时只会执行一次
三、设置Activity的android:configChanges="keyboardHidden"时,切屏仍是会从新调用各个生命周期,切横、竖屏时只会执行一次
四、设置Activity的android:configChanges="orientation|screenSize|keyboardHidden"时,切屏不会从新调用各个生命周期,只会执行onConfigurationChanged方法