Activity.docx
《Activity.docx》由会员分享,可在线阅读,更多相关《Activity.docx(31页珍藏版)》请在冰豆网上搜索。
Activity
目录
一、Activity1
1.Activity的概念与Activity的生命周期图:
1
2.Activity的创建流程2
3.启动和退出一个Activity的几种方式3
4.Activity响应系统状态变化4
5.系统给我们提供的常见的Activity5
6.Activity间的数据传递:
7
7.为Activity设置过场动画8
8.Activity的属性8
9.Task和BackStack的一些概念12
10、UI线程13
二、布局14
1、 LinearLayout(线性布局)14
2、RelativeLayout(相对布局)14
3、TableLayout(表格布局)15
4、FrameLayout(帧布局)16
5、GridLayout(网格布局)16
6、AbsoluteLayout(绝对布局)16
一、Activity
官方介绍:
大概意思:
Activity是一个应用程序的组件,他在屏幕上提供了一个区域,允许用户在上面做一些交互性的操作,比如打电话,照相,发送邮件,或者显示一个地图!
Activity可以理解成一个绘制用户界面的窗口,而这个窗口可以填满整个屏幕,也可能比屏幕小或者浮动在其他窗口的上方!
我们可以得到以下两点信息:
1.Activity用于显示用户界面,用户通过Activity交互完成相关操作
2.一个App允许有多个Activity
1.Activity的概念与Activity的生命周期图:
onPause()和onStop()被调用的前提是:
打开了一个新的Activity!
而前者的旧Activity还是可见状态;后者的就Activity已经不可见。
2.Activity的创建流程
注:
Android中的四大组件,只要你定义了,无论你用没用,都要在AndroidManifest.xml对这个组件进行声明,不然运行时程序会直接退出,报ClassNotFindException…
onCreate()一个参数和两个参数的区别:
在AndroidStudio中重写的Activity的onCreate()方法时会发现有两个参数:
正常只有一个参数:
这个就是5.0给我们提供的新的方法,要用它先得在配置文件中为我们的Activity设置一个属性:
android:
persistableMode="persistAcrossReboots"
然后我们的Activity就拥有了持久化的能力了,一般我们会搭配另外两个方法来使用:
1、publicvoidonSaveInstanceState(BundleoutState,PersistableBundleoutPersistentState)
在下列情况下用:
1、点击home键回到主页或长按后选择运行其他程序
2、按下电源键关闭屏幕
3、启动新的Activity
4、横竖屏切换时,肯定会执行,因为横竖屏切换的时候会先销毁Activity,然后再重新创建
5、重要原则:
当系统“未经你许可”时销毁了你的activity,则onSaveInstanceState会被系统调用,这是系统的责任,因为它必须要提供一个机会让你保存你的数据(你可以保存也可以不保存)。
2、publicvoidonRestoreInstanceState(BundlesavedInstanceState,PersistableBundlepersistentState)
onCreate同样可以从取出前者保存的数据:
一般是在onStart()和onResume()之间执行!
之所以有两个可以获取到保存数据的方法,是为了避免Activity跳转而没有关闭,然后不走onCreate()方法,而你又想取出保存数据~
3.启动和退出一个Activity的几种方式
启动
在Android中我们可以通过下面两种方式来启动一个新的Activity,注意这里是怎么启动,而非启动模式!
!
分为显示启动和隐式启动!
1.显式启动:
通过包名来启动,写法如下:
①最常见的:
startActivity(newIntent(当前Act.this,要启动的Act.class));
②通过Intent的ComponentName:
ComponentNamecn=newComponentName(“当前Act的全限定类名”,”启动Act的全限定类名”);
Intentintent=newIntent();
intent.setComponent(cn);
startActivity(intent);
③初始化Intent时指定包名:
Intentintent=newIntent(“android.intent.action.MAIN”);
intent.setClassName(“当前Act的全限定类名”,”启动Act的全限定类名”);
startActivity(intent);
2.隐式启动:
通过Intent-filter的Action,Category或data来实现这个是通过Intent的*intent-filter*来实现的:
3.另外还有一个直接通过包名启动apk的:
Intentintent=getPackageManager().getLaunchIntentForPackage
(“apk第一个启动的Activity的全限定类名”);
if(intent!
=null)startActivity(intent);
退出
有时我们可能会打开了很多个Activity,突然来个这样的需求,在某个页面可以关掉所有的Activity并退出程序!
就是用一个list集合来存储所有Activity!
1、随时关闭所有Activity
publicclassActivityCollector{
publicstaticLinkedListactivities=newLinkedList();
publicstaticvoidaddActivity(Activityactivity)
{
activities.add(activity);
}
publicstaticvoidremoveActivity(Activityactivity)
{
activities.remove(activity);
}
publicstaticvoidfinishAll()
{
for(Activityactivity:
activities)
{
if(!
activity.isFinishing())
{
activity.finish();
}
}
}
}
2、完全退出App的方法
上面说的是关闭所有Activity的,但是有些时候我们可能想杀死整个App,连后台任务都杀死杀得一干二净的话,可以使用搭配着下述代码使用:
publicvoidAppExit(Contextcontext){
try{
ActivityCollector.finishAll();
ActivityManageractivityMgr=(ActivityManager)context
.getSystemService(Context.ACTIVITY_SERVICE);
activityMgr.killBackgroundProcesses(context.getPackageName());
System.exit(0);
}catch(Exceptionignored){}
}
3、双击退出程序的两种方法:
1)定义一个变量,来标识是否退出
privatestaticbooleanisExit=false;
HandlermHandler=newHandler(){
@Override
publicvoidhandleMessage(Messagemsg){
super.handleMessage(msg);
isExit=false;
}
};
publicbooleanonKeyDown(intkeyCode,KeyEventevent){
if(keyCode==KeyEvent.KEYCODE_BACK){
if(!
isExit){
isExit=true;
Toast.makeText(getApplicationContext(),"再按一次退出程序",
Toast.LENGTH_SHORT).show();
//利用handler延迟发送更改状态信息
mHandler.sendEmptyMessageDelayed(0,2000);
}else{
exit(this);
}
returnfalse;
}
returnsuper.onKeyDown(keyCode,event);}
2)保存点击时间:
//保存点击的时间
privatelongexitTime=0;
publicbooleanonKeyDown(intkeyCode,KeyEventevent){
if(keyCode==KeyEvent.KEYCODE_BACK){
if((System.currentTimeMillis()-exitTime)>2000){
Toast.makeText(getApplicationContext(),"再按一次退出程序",
Toast.LENGTH_SHORT).show();
exitTime=System.currentTimeMillis();
}else{
exit();
}
returnfalse;
}
returnsuper.onKeyDown(keyCode,event);
}
4.Activity响应系统状态变化
前面也也说到了App横竖屏切换的时候会销毁当前的Activity然后重新创建一个,你可以自行在生命周期的每个方法里都添加打印Log的语句,来进行判断,又或者设一个按钮一个TextView点击按钮后,修改TextView文本,然后横竖屏切换,会神奇的发现TextView文本变回之前的内容了!
横竖屏切换时Act走下述生命周期:
onPause->onStop->onDestory->onCreate->onStart->onResume
关于状态变化可能遇到下述问题:
1、如何禁止屏幕横竖屏自动切换
在AndroidManifest.xml中为Act添加一个属性:
android:
screenOrientation
有下述可选的值:
unspecified:
默认值由系统来判断显示方向.判定的策略是和设备相关的,所以不同的设备会有不同的显示方向.
landscape:
横屏显示(宽比高要长)
portrait:
竖屏显示(高比宽要长)
user:
用户当前首选的方向
behind:
和该Activity下面的那个Activity的方向一致(在Activity堆栈中的)
sensor:
有物理的感应器来决定。
如果用户旋转设备这屏幕会横竖屏切换。
nosensor:
忽略物理感应器,这样就不会随着用户旋转设备而更改了(”unspecified”设置除外)。
2.横竖屏时想加载不同的布局:
1)准备两套不同的布局,Android会自己根据横竖屏加载不同布局:
创建两个布局文件夹:
layout-land横屏,layout-port竖屏
然后把这两套布局文件丢这两文件夹里,文件名一样,Android就会自行判断,然后加载相应布局了!
2)自己在代码中进行判断,自己想加载什么就加载什么:
我们一般是在onCreate()方法中加载布局文件的,我们可以在这里对横竖屏的状态做下判断,关键代码如下:
if(this.getResources().getConfiguration().orientation==Configuration.ORIENTATION_LANDSCAPE){
setContentView(R.layout.横屏);
}
elseif(this.getResources().getConfiguration().orientation==Configuration.ORIENTATION_PORTRAIT){
setContentView(R.layout.竖屏);
}
3、通过onConfigurationChanged拦截横竖屏变换
Activity每次横竖屏切换都会重新调用onPause->onStop->onDestory->onCreate->onStart->onResume,为此涉及到内容和数据的保存和读取,否则转屏之前的内容就会消失了。
很多时候这样的结果让程序繁琐,为此Android提供了在manifest中设置android:
configChanges属性,从而让Activity不延续上述的重建流程。
在Android工程的Mainfest.xml中配置Activity:
android:
configChanges="keyboardHidden|orientation",横竖屏切换之后就不会去执行OnCreat函数了,而是会去调用onConfigurationChanged()这样就能控制横竖屏的切换了。
用户可以在Activity或View的onConfigurationChanged(ConfigurationnewConfig)函数中获取当前横竖屏参数。
至于其调用顺序跟touch时间的传递顺序相似,不过他没有消费事件的概念,会顺次调用到每一个onConfigurationChanged函数。
需要重写Activity的onConfigurationChanged方法。
实现方式如下,不需要做太多的内容:
@Override
publicvoidonConfigurationChanged(ConfigurationnewConfig){
super.onConfigurationChanged(newConfig);
if(this.getResources().getConfiguration().orientation==Configuration.ORIENTATION_LANDSCAPE){
//landdonothingisok
}elseif(this.getResources().getConfiguration().orientation==Configuration.ORIENTATION_PORTRAIT){
//portdonothingisok
}
}
需要注意的是,onConfigurationChanged函数中只能获得横竖屏切换后的参数,在该函数中获取不到新的Layout和控件的尺寸位置信息,如果要处理尺寸和位置信息,必须通过消息异步或者延时调用。
4.状态保存问题:
这个上面也说过了,通过一个BundlesavedInstanceState参数即可完成!
三个核心方法:
onCreate(BundlesavedInstanceState);
onSaveInstanceState(BundleoutState);
onRestoreInstanceState(BundlesavedInstanceState);
你只重写onSaveInstanceState()方法,往这个bundle中写入数据,比如:
outState.putInt(“num”,1);
这样,然后你在onCreate或者onRestoreInstanceState中就可以拿出里面存储的数据,不过拿之前要判断下是否为null
savedInstanceState.getInt(“num”);
5.系统给我们提供的常见的Activity
//1.拨打电话
//给移动客服10086拨打电话
Uriuri=Uri.parse("tel:
10086");
Intentintent=newIntent(Intent.ACTION_DIAL,uri);
startActivity(intent);
//2.发送短信
//给10086发送内容为“Hello”的短信
Uriuri=Uri.parse("smsto:
10086");
Intentintent=newIntent(Intent.ACTION_SENDTO,uri);
intent.putExtra("sms_body","Hello");
startActivity(intent);
//3.发送彩信(相当于发送带附件的短信)
Intentintent=newIntent(Intent.ACTION_SEND);
intent.putExtra("sms_body","Hello");
Uriuri=Uri.parse("content:
//media/external/images/media/23");
intent.putExtra(Intent.EXTRA_STREAM,uri);
intent.setType("image/png");
startActivity(intent);
//4.打开浏览器:
//打开Google主页
Uriuri=Uri.parse("");
Intentintent=newIntent(Intent.ACTION_VIEW,uri);
startActivity(intent);
//5.发送电子邮件:
(阉割了Google服务的没戏!
!
!
!
)
//给someone@发邮件
Uriuri=Uri.parse("mailto:
someone@");
Intentintent=newIntent(Intent.ACTION_SENDTO,uri);
startActivity(intent);
//给someone@发邮件发送内容为“Hello”的邮件
Intentintent=newIntent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL,"someone@");
intent.putExtra(Intent.EXTRA_SUBJECT,"Subject");
intent.putExtra(Intent.EXTRA_TEXT,"Hello");
intent.setType("text/plain");
startActivity(intent);
//给多人发邮件
Intentintent=newIntent(Intent.ACTION_SEND);
String[]tos={"1@","2@"};//收件人
String[]ccs={"3@","4@"};//抄送
String[]bccs={"5@","6@"};//密送
intent.putExtra(Intent.EXTRA_EMAIL,tos);
intent.putExtra(Intent.EXTRA_CC,ccs);
intent.putExtra(Intent.EXTRA_BCC,bccs);
intent.putExtra(Intent.EXTRA_SUBJECT,"Subject");
intent.putExtra(Intent.EXTRA_TEXT,"Hello");
intent.setType("message/rfc822");
startActivity(intent);
//6.显示地图:
//打开Google地图中国北京位置(北纬39.9,东经116.3)
Uriuri=Uri.parse("geo:
39.9,116.3");
Intentintent=newIntent(Intent.ACTION_VIEW,uri);
startActivity(intent);
//7.路径规划
//路径规划:
从北京某地(北纬39.9,东经116.3)到上海某地(北纬31.2,东经121.4)
Uriuri=Uri.parse("116.3&daddr=31.2121.4");
Intentintent=newIntent(Intent.ACTION_VIEW,uri);
startActivity(intent);
//8.多媒体播放:
Intentintent=newIntent(Intent.ACTION_VIEW);
Uriuri=Uri.parse("file:
///sdcard/foo.mp3");
intent.setDataAndType(uri,"audio/mp3");
startActivity(intent);
//获取SD卡下所有音频文件,然后播放第一首=-=
Uriuri=Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI,"1");
Intentintent=newIntent(Intent.ACTION_VIEW,uri);
startActivity(intent);
//9.打开摄像头拍照:
//打开拍照程序
Intentintent=newIntent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent,0);
//取出照片数据
Bundleextras=intent.getExtras();
Bitmapbitmap=(Bitmap)extras.get("data");
//另一种:
//调用系统相机应用程序,并存储拍下来的照片
Intentintent=newIntent(MediaStore.ACTION_IMAGE_CAPTURE);
time=Calendar.getInstance().getTimeInMillis();
intent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(newFile(Environment
.getExternalStorageDirectory(