Author:ProZoom
Hobby:爱折腾、爱思考,想静静的ProZoom
Github --- 简书 --- CSDN --- 关于我
1 创建表示层(Activity)
1.1定义Activity ,继承Activity
在AndroidManifest.xml的<application>节点中声明<activity>
<activity
android:name="com.itheima.intent.SecondActivity"
android:label="@string/title_activity_second" >
//这两句可以指定手机home里所是否显示的程序图标
</activity >
1.2显式意图创建方式
构造函数,代码少
startActivity(new Intent( this,SecondActivity.class));
类名形式,灵活,可扩展性强
intent.setClassName(this, "cn.itcast.activity.NewActivity");
包名类名形式,可启动其他程序中的Activity
intent.setClassName("cn.itcast.downloader", "cn.itcast.downloader.MainActivity");
1.3 创建Activity并传递数据
在意图对象中封装了一个Bundle对象,可以用来携带数据
在新Activity中可以获得意图对象以获取其中Bundle保存的数据
Intent intent = new Intent();
Bundle extras = new Bundle();
extras.putString("key", "value");
intent.putExtras(extras);
startActivity(intent);
1.4 创建Activity获取返回数据
使用startActivityForResult(Intent intent, int requestCode) 方法打开Activity
重写onActivityResult(int requestCode, int resultCode, Intent data) 方法
新Activity中调用setResult(int resultCode, Intent data) 设置返回数据之后,关闭Activity就会调用onActivityResult方法
Intent intent = new Intent();
intent.putExtra("key", "value");
intent.setClassName(this, "cn.itcast.activity.NewActivity" );
startActivityForResult(intent,100);
------------------------------------------------
@Override
/**
* requestCode 请求码
* resultCode 响应码
* data 返回数据
*/
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//设置返回数据之后,关闭Activity就会调用onActivityResult方法
}
1.5 隐式意图创建Activity
显式意图是指在创建意图时指定了组件,而隐式意图则不指定组件,通过动作、类型、数据匹配对应的组件
在清单文件中定义<activity>时需要定义<intent-filter>才能被隐式意图启动
<intent-filter>中至少配置一个<action>和一个<category>,否则无法被启动
Intent对象中设置的action、category、data在<intent-filter>必须全部包含才能启动
<intent-filter>中的<action>、<category>、<data>都可以配置多个,Intent对象中不用全部匹配,每样匹配一个即可启动
如果一个意图可以匹配多个Activity,Android系统会提示选择
<activity
android:name="com.itheima.intent.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Intent intent = new Intent(this,SecondActivity.class);
intent.setAction( Intent.ACTION_APP_ERROR);
startActivity(intent);
1.6 手动退出当前Activity
调用finish()方发,可以复写此方法,自定义按返回键所发生的事件。
2 生命周期
2.1 Acitivity三种存活状态
Active 运行:activity在最前端运行,处于屏幕前景(当前task的栈顶Activity处于Active状态),同一时刻只能有一个Activity处于Active状态。
Stopped 停止:activity不可见,完全被覆盖,但依然保持所有的状态和内存信息。
Paused 暂停:activity可见,但前端还有其他activity,处于背景画面画面状态,失去了焦点,但依然是活动状态。
2.2 Activity的生命周期可以分为三组
完整的生命周期 oncreate - onstart - onresume - onpause - onstop - ondestroy
可视生命周期 onstart - onresume - onpause - onstop - onstart - onresume
前台生命周期 onresume - onpause
2.3各种状态之间通过下列的方法调用转换
onCreate:创建时调用,或者程序在暂停、停止状态下被杀死之后重新打开时也会调用。在activity第一次被创建的时候调用。这里是你做所有初始化设置的地方──创建视图、设置布局、绑定数据至列表等。如果曾经有状态记录(参阅后述Saving Activity State。),则调用此方法时会传入一个包含着此activity以前状态的包对象做为参数。
onDestroy:销毁时调用,在activity销毁前调用。这是activity接收的最后一个调用。这可能发生在activity结束(调用了它的 finish() 方法)或者因为系统需要空间所以临时的销毁了此acitivity的实例时。你可以用isFinishing() 方法来区分这两种情况。
onStart:当activity正要变得为用户所见时被调用,
onStop:进入停止状态,或者销毁时会调用,当activity不再为用户可见时调用此方法。这可能发生在它被销毁或者另一个activity(可能是现存的或者是新的)回到运行状态并覆盖了它。
onResume:onStart之后或者从暂停状态恢复时调用,从停止状态恢复时由于调用onStart,也会调用onResume,在activity开始与用户进行交互之前被调用。此时activity位于堆栈顶部,并接受用户输入。
onPause:进入暂停、停止状态,或者销毁时会调用,当系统将要启动另一个activity时调用。此方法主要用来将未保存的变化进行持久化,停止类似动画这样耗费CPU的动作等。这一切动作应该在短时间内完成,因为下一个activity必须等到此方法返回后才会继续。
onRestart:从停止状态恢复时调用,在activity执行onStop()停止后,在再次启动之前被调用。
总以onStart()继之。
2.4 保存信息的方法
onSaveInstanceState:在Activity被动的摧毁或停止的时候调用,用于保存运行数据,可以将数据存在在Bundle中
onRestoreInstanceState:该方法在Activity被重新绘制的时候调用,例如改变屏幕方向,savedInstanceState为onSaveInstanceState保存的数据
2.5 Activity生命周期总结
1,Activity运行时按下HOME键(跟被完全覆盖是一样的):onSaveInstanceState --> onPause --> onStop onRestart -->onStart--->onResume
2,Activity未被完全覆盖只是失去焦点:onPause--->onResume
3,当前Activity产生事件弹出Toast和AlertDialog的时候Activity的生命周期不会有改变
3 启动模式
activity的任务栈的概念:
activity task stack
activity stack
back stack 后退栈
在Android系统中我们创建的Acitivity是以栈的形式呈现的
Actvity的启动模式
在AndroidManifest.xml中的<activity>标签中可以配置android:launchMode属性,用来控制Actvity的启动模式
<activity
android:launchMode="singleInstance"
android:name="com.itheima.mode.A_Activity"
android:label="14.A_Activity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:launchMode="singleInstance"
android:name="com.itheima.mode.B_Activity"
android:label="14.B_Activity" >
</activity>
Activity有四种加载模式:
standard、singleTop、singleTask、singleInstance(其中前两个是一组、后两个是一组),默认为standard
standard:就是intent将发送给新的实例,所以每次跳转都会生成新的activity。
singleTop:也是发送新的实例,但不同standard的一点是,在请求的Activity正好位于栈顶时(配置成singleTop的Activity),不会构造新的实例
singleTask:和后面的singleInstance都只创建一个实例,当intent到来,需要创建设置为singleTask的Activity的时候,系统会检查栈里面是否已经有该Activity的实例。如果有直接将intent发送给它。
singleInstance:首先说明一下task这个概念,Task可以认为是一个栈,可放入多个Activity。比如启动一个应用,那么Android就创建了一个Task,然后启动这个应用的入口Activity,那在它的界面上调用其他的Activity也只是在这个task里面。那如果在多个task中共享一个Activity的话怎么办呢。举个例来说,如果开启一个导游服务类的应用程序,里面有个Activity是开启GOOGLE地图的,当按下home键退回到主菜单又启动GOOGLE地图的应用时,显示的就是刚才的地图,实际上是同一个Activity,实际上这就引入了singleInstance。singleInstance模式就是将该Activity单独放入一个栈中,这样这个栈中只有这一个Activity,不同应用的intent都由这个Activity接收和展示,这样就做到了共享。当然前提是这些应用都没有被销毁,所以刚才是按下的HOME键,如果按下了返回键,则无效
//可以有多个A
standard:每次调用startActivity()启动时都会创建一个新的Activity放在栈顶
singleTop:启动Activity时,指定Activity不在栈顶就创建,如在栈顶,则不再创建
//单例的,不能使用返回数据方法
singleTask:如果启动的Activity不存在就创建,如果存在直接跳转到指定的Activity所在位置
singleInstance:如果启动的Activity不存在就创建,如果存在就将指定的Activity移动到栈顶
6 android推出activity的方式总结
在android中使用:[activityname].this.finish(); 只是退出了activity的堆栈中,要真正的退出程序在手机cpu中的运行,当应用不再使用时,通常需要关闭应用,可以使用以下三种方法关闭android应用:
一 使用killProcess()函数,首先获取当前进程的id,然后杀死该进程:
android.os.Process.killProcess(android.os.Process.myPid());
通过这种方式不能将应用程序完全杀死,并且他不会把当前应用应用的Activity的task任务栈清空
二 在activity的生命周期函数中添加如下的函数,强制关闭与该包有关联的一切执行:
ActivityManager am = (ActivityManager)getSystemService (Context.ACTIVITY_SERVICE);
am.restartPackage("packagename");
或杀死 am.killBackgroundProcesses(info.getPackname());
还需要在AndroidManifest.xml文件中加入如下的权限:<uses-permission android:name="android.permission.RESTART_PACKAGES" />
此做法:只能杀死别人,不能杀死自己
三、 终止当前正在运行的Java虚拟机,导致程序终止
System.exit(0);
不会把自己的应用程序杀死
企业中做法:
创建类app 继承Application
AndroidMainfest -->name -->app //声明该类为整个应用程序全局的实例
创建整个应用程序全局的实例
App.class:
ArrayList<Activity> activities;
其他的Activity中:
public void onCreate(Bundle savedInstanceState) {
App app = (App) getApplication();//获取应用程序全局的实例引用
app.activities.add(this); //把当前Activity放入集合中
}
public void onDestory(){
App app = (App) getApplication();//获取应用程序全局的实例引用
app.activities.remove(this); //把当前Activity从集合中移除
}
安全退出:
在菜单退出按钮的事件中定义如下代码:
App app = (App) getApplication();
List<Activity> activities = app.activities;
for(Activity act:activities){
act.finish();//显式结束
}
2.3以后应用不能完全退出,被屏蔽了。怎样完全退出呢?
由于android 是 基于liux 操作系统的, 所以 一般情况下 我们 使用
android.os.Process.killProcess(android.os.Process.myPid()); 这个方法就可以杀掉进程,
不过当 activity 多的时候,而且当我们忘记finish 其中的某几个,或者说,你对 AndroidMainfest.xml 中的 每个 Activity 中 android:launchMode , android:alwaysRetainTaskState 这些都不是很清楚时,就会出现 应用的 关闭不完全,主要原因是由于 残留的 Activity 本身是一个进程,所以系统又把这个Activity提到了最前面,就会使我们的程序没有完全关闭,
那么 再 1.5---2.1 用了一个 方法,都可以成功的解决这个问题,那就是
final ActivityManager am = (ActivityManager) ACTIVITY
// .getSystemService(Context.ACTIVITY_SERVICE);
// am.restartPackage(ACTIVITY.getPackageName());
但是到了 2.2 的时候, 这个方法,就不奏效了, 那么我想请问 各位同仁们,有没有 什么通用的办法呢~~~~
这个问题,网上的童鞋,也是有非常多做法,android123 也给我们提供了,非常多的解决办法, 但是小弟不才,他们提供的方法,有些时候,不管用,所以很费脑~~~~
现在我将我 这个方法 分享给大家, 这个方法在 1.5--2.3 的机器上都测试过,是可以完全杀死进程的
该方法需要两个必要条件
条件一: 一个自己管理Activity 的列表, 网上很多用 ArryList 来存储acitivity
条件二: 需要一段,重新开启堆栈,跳转到 Home界面,并且 用liux的杀掉进程的方法
代码如下
protected void quit()
{
int size = activityManager.activityStackCount();
for(int i =size-1 ; i > 0 ;i--)
{
Activity activity = activityManager.allTaskActivity().get(i);
activityManager.popActivity(activity);
}
activityManager = null;
getActivity().finish();
//目前最为通用的 关闭进程的方法以后的版本使用
Intent startMain = new Intent(Intent.ACTION_MAIN);
startMain.addCategory(Intent.CATEGORY_HOME);
startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(startMain);
android.os.Process.killProcess(android.os.Process.myPid());
}
7 any tips
一些关于 Activity 的技巧
锁定 Activity 运行时的屏幕方向
Android 内置了方向感应器的支持。在 G1 中,Android 会根据 G1 所处的方向自动在竖屏和横屏间切换。但是有时我们的应用程序仅能在横屏 / 竖屏时运行,比如某些游戏,此时我们需要锁定该 Activity 运行时的屏幕方向,<activity >节点的 android:screenOrientation属性可以完成该项任务,示例代码如下:
<activity android:name=".EX01"
android:label="@string/app_name"
android:screenOrientation="portrait">// 竖屏 , 值为 landscape 时为横屏
…………
</activity>
全屏的 Activity
要使一个 Activity 全屏运行,可以在其 onCreate()方法中添加如下代码实现:
// 设置全屏模式
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
// 去除标题栏
requestWindowFeature(Window.FEATURE_NO_TITLE);
在 Activity 的 Title 中加入进度条
为了更友好的用户体验,在处理一些需要花费较长时间的任务时可以使用一个进度条来提示用户“不要着急,我们正在努力的完成你交给的任务”。如下图:
在 Activity 的标题栏中显示进度条不失为一个好办法,下面是实现代码:
// 不明确进度条
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.main);
setProgressBarIndeterminateVisibility(true);
// 明确进度条
requestWindowFeature(Window.FEATURE_PROGRESS);
setContentView(R.layout.main);
setProgress(5000);