【Android】四大组件(1)Activity详解

准备将Android再系统的学一下,之前的学习属于项目驱动型,要实现什么功能,就去网上搜,各种抄代码,堆接口,最终一个臃肿的项目搭建出来,之前对java的学习也是匆匆的过了一遍,面向对象的思维都没有形成,只是会基础语法,设计模式更是完全不会有考虑。通过这么系统的学一遍算是把之前的琐碎的点再重新拾起来吧。

Android四大组件

组件(Component)是对数据和方法的简单封装。
控件:UI组件

Activity,Service,Broadcast,ContentProvider

Activity

今天学习的是Activity,Activity这个也是最重要的,因为我们Android程序中,我们所能够看到的都是通过Activity来进行表达,通过Activity实现人机交互,其重要性不言而喻。

1.Activity的生命周期
2.Activity的启动模式
3.Activity间通信
4.Activity的管理
5.Activity回收,重利用问题

Activity的生命周期

Activity中有6个回调方法

public class MainActivity extends Activity {

    /*Activity第一次被创建的时候调用,在这个方法里执行一些初始化操作和布局加载
    * 其中的参数是我们的Activity被销毁的时候再次被重新创建的时候保留的一些数据。
    * */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    /*在OnCreate方法执行之后再执行,在由不可见变化成可见的时候调用
     */

    @Override
    protected void onStart() {
        super.onStart();
    }

    /*当Activity准备和用户进行交互的时候被调用,此时的Activity一定是处于栈顶
     */

    @Override
    protected void onResume() {
        super.onResume();
    }

    /*准备去启动一些其他的Activity或者是恢复其它的Activity的时候被调用,此时执行的操作是
    保存当前Activity的一些数据,同时释放掉前一个Activity消耗cpu的操作
     */

    @Override
    protected void onPause() {
        super.onPause();
    }

    /*
    当前活动完全不可见的时候执行,如果是Dialog,那么此时该方法是不会被执行的
     */

    @Override
    protected void onStop() {
        super.onStop();
    }

    /*
    在活动被销毁的时候进行调用
     */

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    /*
    当活动再次被启动的时候调用
     */

    @Override
    protected void onRestart() {
        super.onRestart();
    }
}

Activity不可见:
OnCreate(),OnStart(),OnStop(),OnDestroy()
Activity可见:
OnResume(),OnPause()

Activity的启动模式

对于每个启动的应用,会存在一个任务栈,栈中存放着我们的Activity,处于栈顶的Activity是可交互的,不同的启动模式,Activity在栈中的有不同的操作。Activity拥有四种启动模式,(standard,singleTop,singleTask,singleInstance)我们在AndroidMainfeast文件中注册Activity的时候对其尽心设置。(对于四大组件,必须要进行注册,否则是无法使用的)

 <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".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>
 </application>

Application的一个属性,allowBackup(Android API Level 8 及其以上 Android 系统提供了为应用程序数据的备份和恢复功能,此功能的开关决定于该应用程序中 AndroidManifest.xml 文件中的 allowBackup 属性值,其属性值默认是 True。当 allowBackup 标志为 true 时,用户即可通过 adb backup 和 adb restore 来进行对应用数据的备份和恢复,这可能会带来一定的安全风险。)

此处的Activity没有启动模式的属性,没有显示的指定,此时为默认的启动属性,即为standard

standard

该种模式下,我们启动一个Activity后,该Activity就会被压入到栈中,然后当我们再次启动这个Activity的时候,无论返回栈中有没有该栈,都会重新再启动一个Activity

singleTop

当返回栈的栈顶已经是要启动的Activity,则不会再重新启动一个

singleTask

当我们在创建Activity实例的时候,如果发现返回栈中存在Activity实例,那么直接调用原来的实例,此时该实例会成为栈顶,而之前在该实例上的活动实例,这个时候都会被清理掉。

singleInstance

使用场景:不同的应用程序调用同一个Activity,如果一个Activity的启动模式被设置成为该种模式,会为该Activity单独开出一个栈,然后不会因为栈中其它的Activity受到影响。

Activity间通信

在Activity之间,我们需要进行一些数据,信息的交互,传递,通常会通过Intent来实现,Android的各个组件也是通过这个进行通信。不仅可以执行一些动作,同时还可以进行一些数据的传递。

显式的使用Intent

实现Activity的跳转

public void activitySkip(){
        Intent intent = new Intent(MainActivity.this,SubActivity.class);
        startActivity(intent);
    }
隐式的使用Intent

上面的代码实例,通过制定当前的Activity和要跳转的Activity来实现跳转,而Android系统还提供了另一种隐式的启动Activity的方式,就是在AndroidMainfeast中对Activity的一些属性(action,category)进行设置,然后系统对这个Intent进行分析即可得到其行为。

<intent-filter>
  <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

我们可以自定义action的名字,category的内容,然后通过对Intent的设置就可以实现隐式的使用

<activity
    android:name=".SubActivity"
    android:label="@string/title_activity_sub" >
    <intent-filter>
        <action android:name="androidstudy.intent.action.SUBACTIVTY"/>
        <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>
</activity>

action的名字自己可以随意的取

Intent intent = new Intent("androidstudy.intent.action.SUBACTIVTY");
startActivity(intent);

通过Intent隐式调用其它应用程序Activity

我们在应用程序中,如果要打开其中的一个链接,通常会调用本地的浏览器,这就是通过Intent进行的隐式调用,我们的应用程序中比如对相机,拨号等的调用都是通过这种方式来实现的,从而让我们在进行应用程序开发的时候能够更好地专注我们所要实现的主要功能。

public void openURL(){
        Intent intent = new Intent("Intent.ACTION_VIEW");
        intent.setData(Uri.parse("http://www.baidu.com"));
        startActivity(intent);
    }

使用本地浏览器打开百度首页,Android系统提供了很多action,通过相应的action,我们可以实现调用本地不同的应用内的activity来实现不同的操作。同时我们也可以通过对自己应用内的activity设置相应action,从而使其拥有相应的功能。

通过Intent进行数据传递

普通数据传递

public void dataDeliver(){
        Intent intent = new Intent(MainActivity.this,SubActivity.class);
        intent.putExtra("key","value");
        startActivity(intent);
    }

当我们需要传输的数据比较多的时候,我们通常会使用bundle来进行数据的携带

 public void dataDeliver(){
        Bundle bundle = new Bundle();
        bundle.putString("key","value");
        Intent intent = new Intent(MainActivity.this,SubActivity.class);
        intent.putExtras(bundle);
        startActivity(intent);
    }

那么数据在另一端如何被接收呢?

public void getData(){
        Intent intent = getIntent();
        String str = intent.getStringExtra("key");
        Bundle bundle = intent.getExtras();
        bundle.getString("key");
}

首先要获得这个Intent,然后根据相应的key值来得到具体的数据。
上述都是通过Intent来实现对向下一个activity的跳转的时候数据的传递,如何向上一个activity传递数据呢?毫无疑问,要通过回调方法来实现。

 public void dataDeliver(){
        Bundle bundle = new Bundle();
        bundle.putString("key", "value");
        Intent intent = new Intent(MainActivity.this,SubActivity.class);
        intent.putExtras(bundle);
        startActivityForResult(intent,1);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode){
            case 1:
                String str = data.getStringExtra("key");
                break;
        }
    }

requestCode是我们在向其他的activity进行跳转的时候设置的一个code用来区分不同的activity,resultCode是我们在一个activity中处理完相应的操作后生成的用来判断成功与否,最后是我们所要传递的数据。

在另一个activity中,在将该activity结束掉的时候,我们要对Intent进行相应的操作设置。

public void finishActivity(){
        Intent intent = new Intent();
        intent.putExtra("key","str");
        setResult(RESULT_OK,intent);
}

Intent安全问题:我们可以在我们的应用内对其它的应用的activity进行相应的调用,那么我们的应用中,通过getIntent来获取数据的时候,如果数据中存在错误或者是不符合规范,那么我们就会出现导致应用程序奔溃的问题。
本地应用程序拒绝服务漏洞:
漏洞位置:处理 getIntent() 的 intent 附带的数据
漏洞触发前提条件
getIntent() 的 intent 附带空数据、异常或畸形数据
处理 getXXXExtra() 获取的数据时没有进行异常捕获
漏洞原理:Android 系统中提供了 Intent 机制来协助应用间的交互与通讯,其负责对应用中一次操作的动作、动作涉及数据、附加数据进行描述,系统则根据此 Intent 的描述,负责找到对应的组件,将 Intent 传递给调用的组件,并完成组件的调用。调用的组件在处理 Intent 附加数据的时候,没有进行异常捕获,因此当处理空数据、异常或者畸形数据时,导致应用崩溃。

Activity的管理

我们的一个应用程序会存在很多的activity,当我们要关闭一个应用程序的时候,我们可能想直接将其完全关闭,而不是一次推出一个栈,所以需要一个对所有activity进行管理的一个类。再就是当我们协同开发很多页面的应用的时候,我们要如何知道打开的哪一个页面对应哪一个activity呢?解决方法,解决上述两个问题,在activity的基础上再建立一个类,然后将相应的操作加入到其中,然后再通过一个activity控制类,来实现对所有activity的控制。

public class ActivityManager {

//用来存放activity的列表
    public static List<Activity> activities = new ArrayList<Activity>();

//添加activity
    public static void addActivity(Activity activity){
        activities.add(activity);
    }

//移除activity
    public static void removeActivity(Activity activity){
        activities.remove(activity);
    }

//结束掉所有activity
    public static void finishAll(){
        for(Activity activity:activities){
            if(!activity.isFinishing()){
                activity.finish();
            }
        }
    }

}

通过这一个管理类,我们对其activity进行添加,删除的管理,为了能够减少代码量,我们在activity的基础上再构建一个类,然后让我们用到的activit都从其上面继承。

public class BaseActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityManager.addActivity(this);
        Log.i("Activity",getClass().getSimpleName());
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        ActivityManager.removeActivity(this);
    }
}

通过上面两个类,我们能够很好的实现对于activity的一个把控。

Activity的数据保存

当由于内存问题,我们的Activity被终结掉后,我们再次从返回栈中回到Activity的时候,此时的Activity是被重新创建的。Android提供了一个方法,通过这个方法,我们可以在activity被结束掉的时候,通过bundle携带一些临时状态数据。

@Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString("key","value");
    }

在我们activity被重新启动的时候,我们就可以从bundle里获取相应的数据。

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //判断数据是否为空,然后取其中的数据进行处理
        if(savedInstanceState!=null){
            Do something.
        }
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值