Android 四大组件之一 Activity

1. 什么是Activity?

Activity是安卓四大组件之一,一个用户交互对应一个Activity

Activity常见方法

set Content View() 要显示的布局

Activity是Contxt的子类,同时实现了windowCallBack和keyevent,可以处理与窗口用户交互事件

2.描述生命周期

Activity 从创建到销毁有多种的状态,从一种状态到另一种状态会激发相应的接口回掉方法,

这些接口回掉方法包括onCreat()、onStart()、onResume()、onPause()、onStop()、onReStrat()、onDestroy()

其实这些方法都是一一对应的 比如说 onCreat() 对应 onDestroy()

void onCreate(Bundle savedInstanceState)

void onStart() activity变为在屏幕上对用户可见时调用。

void onResume() activity开始与用户交互时调用(无论是启动还是重新启动一个活动,该方法总是被调用的)。

void onPause() activity被暂停或收回cpu和其他资源时调用,该方法用于保存活动状态的,也是保护现场,压栈吧!

void onStop() activity被停止并转为不可见阶段及后续的生命周期事件时调用。

void onRestart() 重新启动activity时调用。该活动仍在栈中,而不是启动新的活动。

void onDestroy() activity被完全从系统内存中移除时调用,该方法被调用可能是因为有人直接调用onFinish()方法或者系统决定停止该活动以释放资源!

Android 四大组件之一 Activity

常见的几种Activity生命周期执行顺序

第一次启动Activity的时候执行的方法

onCreat()、onStart()、onResume()

当我们点击Back退回桌面的时候依次调用

onPause()-->onStop()-->onDestory()

当我们点击home按键的时候

onPause()、onSaveInstanceState()、onStop()

当我们手机灭屏的时候

onPause()、onSaveInstanceState()、onStop()

当我们手机开屏的时候

onRestart()、onStart()、onResume()

当地一个页面跳转到第二个页面

onPause()、onSaveInstanceState()、onStop、 onCreat()、onStart()、onResume()

当我们在home按键的时候如果向保存状态最好在 onPause() 或者在onStop()进行保存状态,在onRestart() 进行获取数据

在切换横竖屏的时候生命周期的方法会执行

1 切换到横屏

onSaveInstanceState

onPause

onStop

onDestroy

onCreate

onStart

onRestoreInstanceState

onResume

2 切换到竖屏,销毁了两次

onSaveInstanceState

onPause

onStop

onDestroyonCreate

onStart

onRestoreInstanceState

onResume

onSaveInstanceState

onPause

onStop

onDestroy

onCreate

onStart

onRestoreInstanceState

onResume

3 修改AndroidManifest.xml,把该Activity添加 android:configChanges="orientation",切横屏,只销毁一次。

onSaveInstanceState

onPause

onStop

onDestroy

onCreate

onStart

onRestoreInstanceState

onResume

4 再切回竖屏,发现不会再打印相同信息,但多打印了一行onConfigChanged

onSaveInstanceState

onPause

onStop

onDestroy

onCreate

onStart

onRestoreInstanceState

onResume

onConfigurationChanged

5 更改 android:configChanges="orientation" 改成 android:configChanges="orientation|keyboardHidden",切横屏,就只打印onConfigChanged

onConfigurationChanged

6 切回竖屏

onConfigurationChanged

onConfigurationChanged

总结:

1、不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次

2、设置Activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次

3、设置Activity的android:configChanges="android:configChanges="orientation|keyboardHidden|screenSize"

"时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法。(执行这个方法,必须设置sdk version 大于等于13.0

3.启动一个Activity的几种方式

这里的启动不是启动模式 可分为两种启动 一种是

显示启动和隐式启动!

我们常见的跳转方式就是startActivity(new Intent(当前Act.this,要启动的Act.class));

多个Activity交互(后一个传给前一个)

使用步骤

1.使用start ActivityForResult(Intent intent,int requestCode)来启动一个Activity

2.在启动的Activity中重写onActivityResult(int requestCode,int resultCode,Intent data)

requestCode是用于区分在该Activity中不同的启动方式,比如两个不同的按钮,启动的是同一个Activity。传递的数据可能不同,这里就可以用requestCode来区别resultCode:子Activity通过setResult()返回的码

3.在子Activity重写setResult(int resultCode,Intent data)

下面文件是我们系统中常见的Activity

//1.拨打电话

// 给移动客服10086拨打电话

Uri uri = Uri.parse("tel:10086");

Intent intent = new Intent(Intent.ACTION_DIAL, uri);

startActivity(intent);

 

//2.发送短信

// 给10086发送内容为“Hello”的短信

Uri uri = Uri.parse("smsto:10086");

Intent intent = new Intent(Intent.ACTION_SENDTO, uri);

intent.putExtra("sms_body", "Hello");

startActivity(intent);

 

//3.发送彩信(相当于发送带附件的短信)

Intent intent = new Intent(Intent.ACTION_SEND);

intent.putExtra("sms_body", "Hello");

Uri uri = Uri.parse("content://media/external/images/media/23");

intent.putExtra(Intent.EXTRA_STREAM, uri);

intent.setType("image/png");

startActivity(intent);

 

//4.打开浏览器:

// 打开Google主页

Uri uri = Uri.parse("http://www.baidu.com");

Intent intent  = new Intent(Intent.ACTION_VIEW, uri);

startActivity(intent);

 

//5.发送电子邮件:(阉割了Google服务的没戏!!!!)

// 给[email protected]发邮件

Uri uri = Uri.parse("mailto:[email protected]");

Intent intent = new Intent(Intent.ACTION_SENDTO, uri);

startActivity(intent);

// 给[email protected]发邮件发送内容为“Hello”的邮件

Intent intent = new Intent(Intent.ACTION_SEND);

intent.putExtra(Intent.EXTRA_EMAIL, "[email protected]");

intent.putExtra(Intent.EXTRA_SUBJECT, "Subject");

intent.putExtra(Intent.EXTRA_TEXT, "Hello");

intent.setType("text/plain");

startActivity(intent);

// 给多人发邮件

Intent intent=new Intent(Intent.ACTION_SEND);

String[] tos = {"[email protected]", "[email protected]"}; // 收件人

String[] ccs = {"[email protected]", "[email protected]"}; // 抄送

String[] bccs = {"[email protected]", "[email protected]"}; // 密送

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)

Uri uri = Uri.parse("geo:39.9,116.3");

Intent intent = new Intent(Intent.ACTION_VIEW, uri);

startActivity(intent);

 

//7.路径规划

// 路径规划:从北京某地(北纬39.9,东经116.3)到上海某地(北纬31.2,东经121.4)

Uri uri = Uri.parse("http://maps.google.com/maps?f=d&saddr=39.9 116.3&daddr=31.2 121.4");

Intent intent = new Intent(Intent.ACTION_VIEW, uri);

startActivity(intent);

 

//8.多媒体播放:

Intent intent = new Intent(Intent.ACTION_VIEW);

Uri uri = Uri.parse("file:///sdcard/foo.mp3");

intent.setDataAndType(uri, "audio/mp3");

startActivity(intent);

 

//获取SD卡下所有音频文件,然后播放第一首=-=

Uri uri = Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI, "1");

Intent intent = new Intent(Intent.ACTION_VIEW, uri);

startActivity(intent);

 

//9.打开摄像头拍照:

// 打开拍照程序

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

startActivityForResult(intent, 0);

// 取出照片数据

Bundle extras = intent.getExtras();

Bitmap bitmap = (Bitmap) extras.get("data");

 

//另一种:

//调用系统相机应用程序,并存储拍下来的照片

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

time = Calendar.getInstance().getTimeInMillis();

intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment

.getExternalStorageDirectory().getAbsolutePath()+"/tucue", time + ".jpg")));

startActivityForResult(intent, ACTIVITY_GET_CAMERA_IMAGE);

 

//10.获取并剪切图片

// 获取并剪切图片

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);

intent.setType("image/*");

intent.putExtra("crop", "true"); // 开启剪切

intent.putExtra("aspectX", 1); // 剪切的宽高比为1:2

intent.putExtra("aspectY", 2);

intent.putExtra("outputX", 20); // 保存图片的宽和高

intent.putExtra("outputY", 40);

intent.putExtra("output", Uri.fromFile(new File("/mnt/sdcard/temp"))); // 保存路径

intent.putExtra("outputFormat", "JPEG");// 返回格式

startActivityForResult(intent, 0);

// 剪切特定图片

Intent intent = new Intent("com.android.camera.action.CROP");

intent.setClassName("com.android.camera", "com.android.camera.CropImage");

intent.setData(Uri.fromFile(new File("/mnt/sdcard/temp")));

intent.putExtra("outputX", 1); // 剪切的宽高比为1:2

intent.putExtra("outputY", 2);

intent.putExtra("aspectX", 20); // 保存图片的宽和高

intent.putExtra("aspectY", 40);

intent.putExtra("scale", true);

intent.putExtra("noFaceDetection", true);

intent.putExtra("output", Uri.parse("file:///mnt/sdcard/temp"));

startActivityForResult(intent, 0);

 

//11.打开Google Market

// 打开Google Market直接进入该程序的详细页面

Uri uri = Uri.parse("market://details?id=" + "com.demo.app");

Intent intent = new Intent(Intent.ACTION_VIEW, uri);

startActivity(intent);

 

//12.进入手机设置界面:

// 进入无线网络设置界面(其它可以举一反三)  

Intent intent = new Intent(android.provider.Settings.ACTION_WIRELESS_SETTINGS);  

startActivityForResult(intent, 0);

 

//13.安装apk:

Uri installUri = Uri.fromParts("package", "xxx", null);   

returnIt = new Intent(Intent.ACTION_PACKAGE_ADDED, installUri);

 

//14.卸载apk:

Uri uri = Uri.fromParts("package", strPackageName, null);      

Intent it = new Intent(Intent.ACTION_DELETE, uri);      

startActivity(it);

 

//15.发送附件:

Intent it = new Intent(Intent.ACTION_SEND);      

it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text");      

it.putExtra(Intent.EXTRA_STREAM, "file:///sdcard/eoe.mp3");

sendIntent.setType("audio/mp3");      

startActivity(Intent.createChooser(it, "Choose Email Client"));

 

//16.进入联系人页面:

Intent intent = new Intent();

intent.setAction(Intent.ACTION_VIEW);

intent.setData(People.CONTENT_URI);

startActivity(intent);

 

//17.查看指定联系人:

Uri personUri = ContentUris.withAppendedId(People.CONTENT_URI, info.id);//info.id联系人ID

Intent intent = new Intent();

intent.setAction(Intent.ACTION_VIEW);

intent.setData(personUri);

startActivity(intent);

Activity的状态通常情况下系统会自动保存的,只有当我们需要才使用这样的功能。

一般来说,调用onPause()和onStop()的Activity实例仍然存在于内存中,Activity的所有信息和状态数据不会消失,当Activity重新回到前台之后,所有的改变都会得到保留。

当系统内存不足时,调用onPause() 和 onStop() Activity可能会被销毁,此时内存中就不会有Activity的实例了,如果之后Activity重新回到前台,之前所做的改变就会消失,为了避免这种情况的发生,我们可以覆写onSaveInstanceState()方法。onSaveInstanceState()方法接受一个Bundle类型的参数,开发者可以将状态数据存储到这个Bundle对象中,这样即使Activity被销毁,当用户重新启动这个activity而调用他的onCreate()方法时,上述的Bundle对象会作为参数传递给onCreate()或者onRestoreInstanceState()方法中,开发者可以从Bundle对象中取出保存的数据,然后利用这些数据将Activity恢复之前被销毁的状态

需要注意的是onSaveInstanceState()方法不一定调用,因为这些场景不需要保存状态数据,比如用户再按下Back按键退出activity是 用户显然想要关闭这个activity,此时是没有必要保存数据以供下次回复,也就是说onSaveInstaceState()方法不会被调用,如果调用onSaveInstanceState()方法,调用将发生在onPause() 或 onStop() 方法之前

 

5.如何将一个Activity 设置成窗口的样式?

只需要给我们的activity设置一个属性就可以了

android:theme = "@android:style/Theme.Dialog"

//设置左上角小图标 requestWindowFeature(Window.FEATURE_LEFT_ICON); setContentView(R.layout.main); getWindow().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON, android.R.drawable.ic_lion_icon); //设置文字: setTitle(R.string.actdialog_title); //XML代码中设置:android:label="@string/activity_dialog"

6.Android 中Intent传递数据有大小限制吗,如何解决?

Intent传递数据大小的限制大概在1M左右,超过这个限制就会崩溃。处理方式如下:

进程内:EventBus,文件缓存,磁盘缓存

进程间:通过ContentProvider进行将数据共享和传递

在使用Bundle传递数据时,要注意,Bundle的大小是有限制的 < 0.5MB,如果大于这个值 是会报TransactionTooLargeException异常的!!

7.如何退出所有的Activity?

1.创建一个Activity管理器类:ActivityCollector定义三个共有的静态方法:定义存储Activity的List的集合,方法如下

1.addActivity()往集合中添加Activity对象

2.removeActivity:移除Activity中的对象

3.finishAll 增强for循环遍历所有的Activity调用 if(!activity.isFinishing()) activity.finish()

 

2.BaseActivty中

1.onCreat()方法中添加ActivityCollector.addActivity(this);

2.onDestory()方法添加ActivityCollector.removeActivity(this)

3.可以在任意的Activity中调用ActivityCollector.finishAll()从而关闭所有Activity.退出App

代码实现如下

public class ActivityCollector { public static LinkedList<Activity> activities = new LinkedList<Activity>(); public static void addActivity(Activity activity) { activities.add(activity); } public static void removeActivity(Activity activity) { activities.remove(activity); } public static void finishAll() { for(Activity activity:activities) { if(!activity.isFinishing()) { activity.finish(); } } } }

7.完全退出App的方法

上面说的是关闭所有的Activity的,但是有些时候我们想杀死整个App,连后台任务都杀死

/*

退出应用程序的

*/

public void AppExit(Context context){

    try{

        ActivityAcollect.finishAll();

        ActivityManager activityMgr =(ActivityManger)context.getSystemService(Context.ACTIVITY_SERVICE);

        activiryMgr.killBackGroupProcessec(context.getPackgeName());

        System.exit(0);

    }catch(Exception ignored){}

}

8.Android 中的Context、Activity、Appliction有什么区别?

相同,Activity和Appliction都是Context的子类

Context从字面的意思是上下文的意思,在实际应用中它也确实是起到管理上下文环境中各个参数的变量的总用,方便我们可以简单的访问到各个资源

不同:维护的生命周期不同,Context维护的是当前Activity的生命周期,Appliction维护的是整个项目的生命周期

使用Context的时候,小心内存泄漏,注意一下几个方便

1.不要让生命周期长的对象引用activity context ,即保证引用activity的对象要与activity本身生命周期一样

2.对于生命周期长的对象,可以使用application,context

3.避免非静态的内部类,尽量使用静态类,避免生命周期问题,注意内部类对外部对象引用导致生命周期的变化

9.两个activity之间传值数据,除了intent,广播接收者,context,provider还有啥?

1.利用static静态数据,public static成员变量

2.利用外部存储的传输

例如 File 文件存储

sharePreferences 首选项

sqlite数据库

10.Context 是什么?

1.它描述的是一个应用层序环境的信息,即上下文

2.该类是一个抽象的(abstract class)类,Android 提供 了该抽象类的具体实现类(ContextIml)

3.通过它我们可以获取应用程序的资源类,也包括一些应用级别操作,,例如一个Activity发送广播,接受Intent,信息,等

10.Activity的四种启动模式

Android 四大组件之一 Activity

1.standard模式

标准模式也是activity的默认启动模式,在这种模式下的activity可以被多次实例化,即在同一个任务中可以存在多个activity实例,每个实例都会处理一个intent对象,如果Activity A的启动模式standard ,并且a已经启动,在a中再次启动activity a,即使调用startActivity(new Intent(this,A.class)),会在A的上面再次启动一个A的实例,即当前栈中的状态是A--->A.

2.singleTop模式

栈顶复用模式,如何一个singleTop模式启动的activity的实例,已经存在与任务栈的栈顶,那么启动该这个Activity时,不会创建新的实例,而是重用位于栈顶的那个实例,并且会调用该实例的onNewIntent()方法将Intent对象传递到这个实例中,举例来说如果A的启动时singleTop,并且A的一个实例已经存在与栈顶中,那么再调用startActivity(this,A.class),启2任务栈动A是不会再次创建A的实例是重用原来的实例,并且调用原来的实例的onNewIntent()方法。这时任务栈中还是这又一个A的实例,如果singleTop模式启动的activity的一个实例,已经存在与任务栈中,但是不在栈顶,那么他的行为和standard模式相同,也会创建多个实例.

3.singleTask模式

栈内复用,只允许在系统中有一个Activity实例。如果系统中已经有了一个实例, 持有这个实例的任务将移动到顶部,同时intent将被通过onNewIntent()发送。 如果没有,则会创建一个新的Activity并置放在合适的任务中。

4.singleInstance模式

保证系统无论从哪个Task启动Activity都只会创建一个Activity实例,并将它加入新的Task栈顶 也就是说被该实例启动的其他activity会自动运行于另一个Task中。 当再次启动该activity的实例时,会重用已存在的任务和实例。并且会调用这个实例 的onNewIntent()方法,将Intent实例传递到该实例中。和singleTask相同, 同一时刻在系统中只会存在一个这样的Activity实例。