Android 四大组件之Activity特征及交互

创建Activity

定义类继承自Activity类;

2)在manifest的Application节点中声明<activity>节点;

生命周期

onCreate():

当activity是被创建时候,会自动运行该方法。该方法做一些初始化动作,比如创建views,设置数据到list等等,该方法提供了一个Bundle类型的变量,该变量中有这个activity以前的状态信息,前提是以前存过这些信息。这个方法执行完后执行的是onStart()方法;若在onCreate方法中加入finish()方法,onCreate下一个运行onDestroy方法

onRestart():

把activity从onStop状态唤醒时,会用onRestart方法,该方法优先于再次运行的onStart,运行完onRestart之后运行onStart。若在onRestart()方法中加入finish()语句,则还是会继续运行onStart及后面的状态方法直到onDestroy运行完

onStart():

当activity对用户可见时会调用onStart,当activity在前台显示时,会运行onResume;当activity还没在前台显示就被隐藏(停止状态)了会运行onStop(),比如在onStart方法中用了finish()方法的话,onStart()之后就会直接运行onStop->onDestroy。

onResume():

当activity开始与用户交互时,会调用onResume,并且为了用户操作此时该activity位于activity栈的顶部。经过某些操作后该方法执行完后执行的是onPause()

onPause():

当一个activity运行到onResume方法后,不管是这个activity要销毁还是要暂停或停止,都会调用该方法。这个方法之后有可能是onResume也有可能是onStop,若是在这个activity-A中打开一个不完全覆盖这个activity-A的新activity-B,那么activity-A就会是onPause状态,当activity-B退出时,activity-A就直接运行onResume(前提是onPause的方法执行完了,否则会等onPause方法执行完后才运行onResume方法,所以不建议在这个方法中执行CPU密集的操作)。若是需要退出activity-A,那么下一个就会执行onStop。onPause()用于提交未保存发生变化了的持久化数据,及停止动画及其他其他比较消耗CPU的事件(比如广播接收器,传感器(比如GPS),或者消耗电量的资源),这是为了更好的运行新的activity

onStop():

当这个activity完全看不见的时候,会调用onStop方法,因为另一个activity会调用onResume并且覆盖这个activity。以下三种情况都会使这个activity调用onStop()方法,第一种是一个新的activity被执行,第二种是一个已经存在的activity被切换到最前端,第三种是这个activity要被销毁。如果通过用户召回这个activity,那么会调用onRestart方法;若这个activity要被销毁,则调用onDestroy方法

onDestroy():

当activity销毁前会调用该方法,比如发生如下情况:activity调用了finish()方法来结束这个activity,或者因为系统为了节省空间而临时销毁这个activity,这两个情况可以通过isFinishing()方法判断

总结:

当用户自己退出程序的时候,建议在onStop方法中保存数据;

当用户打开一个新的activity的时候,建议通过onSaveInstanceState来保存数据;这里在网上看到很多人说应该放在onPause里保存,其实我觉得在打开新的一个activity的时候,或者将程序至于后台的时候,都会默认调用onSaveInstanceState方法,而且在这种暂停的状态下,Android的内存管理机制也不太会杀死这种状态的activity。而用onPause保存的时候,若是下一个执行onResume的方法的话,会影响速度,当然数据量小的话也感觉不出来。

先打开ActivityA ,然后再打开ActivityB的生命函数调用流程


Activity的四种启动模式

1 Standard模式

Standard模式是Android的默认启动模式,你不在配置文件中做任何设置,那么这个Activity就是standard模式,这种模式下,Activity可以有多个实例,每次启动Activity,无论任务栈中是否已经有这个Activity的实例,系统都会创建一个新的Activity实例。

2 SingleTop模式

SingleTop模式和standard模式非常相似,主要区别就是当一个singleTop模式的Activity已经位于任务栈的栈顶,再去启动它时,不会再创建新的实例,如果不位于栈顶,就会调用调用onCreat()创建新的实例,现在把配置文件中FirstActivity的启动模式改为SingleTop,我们的应用只有一个Activity,FirstActivity自然处于任务栈的栈顶。这里有一个新的问题,对于每次启动Activity,我们该如何分别处理。答案就是onNewIntent()函数,虽然系统不会调用onCreat(),但会调用onNewIntent,我们可以在这个函数做相应的处理。

3 SingleTask模式

         SingleTask模式的Activity在同一个Task内只有一个实例,如果Activity已经位于栈顶,系统不会创建新的Activity实例,执行onNewIntent(),但Activity已经存在但不位于栈顶时,系统就会把该Activity之上的其他activity移除任务栈(相当于将改activity显示到栈顶),执行onNewIntent()

4 SingleInstance模式

singleInstance模式是单例的,singleTask只是任务栈内单例,系统里是可以有多个singleTask Activity实例的,而singleInstance Activity在整个系统里只有一个实例,启动一singleInstanceActivity时,系统会创建一个新的任务栈,并且这个任务栈只有他一个Activity。

SingleInstance模式并不常用,如果我们把一个Activity设置为singleInstance模式,你会发现它启动时会慢一些,切换效果不好,影响用户体验。它往往用于多个应用之间,例如一个电视launcher里的Activity,通过遥控器某个键在任何情况可以启动,这个Activity就可以设置为singleInstance模式,当在某应用中按键启动这个Activity,处理完后按返回键,就会回到之前启动它的应用,不影响用户体验。

启动Activity的方式 

通过意图(Intent)来启动一个Activity

显示启动

显示启动一般用于自己调用自己的情况(在当前应用找),这样的启动方式比较快速,创建Intent后指定包名和类名;

Intent intent = new Intent(this, OtherActivity.class);

startActivity(intent); // 启动新的Activity

或者:

Intent intent = new Intent();

intent.setClassName("com.itheima.activity", "com.itheima.activity.OtherActivity"); // 包名、全类名

startActivity(intent); // 启动新的Activity

隐式启动

相比于显式Intent,隐式Intnet则含蓄了许多,它并不明确指出我们想要启动哪一个活动,而是指定一系列更为抽象的action和category等信息,然后交由系统去分析这个Intent,并帮我们找出合适的活动去启动

Activity 中 Intent Filter 的匹配过程 : 

这里写图片描述

// 电话

Intent intent = new Intent();

intent.setAction(Intent.ACTION_CALL); // 设置动作

intent.setData(Uri.parse("tel://123456")); // 设置数据

// 音频/视频,设置type

intent.setAction(Intent.ACTION_VIEW);

intent.setDataAndType(Uri.parse("file:///mnt/sdcard/daqin.mp3"), "audio/*"); // 设置数据和数据类型,将启动音频播放器(vedio)

为隐式启动配置意图过滤器

显式意图是指在创建意图时指定了组件,而隐式意图则不指定组件,通过动作、类型、数据匹配对应的组件;

在清单文件中定义<activity>时需要定义<intent-filter>才能被隐式意图启动;

<intent-filter>中至少配置一个<action>和一个<category>,否则无法被启动;

<intent-filter>中的<action><category><data>都可以配置多个,Intent对象中不用全部匹配,每样匹配一个即可启动;

Intent对象中设置的actioncategorydata<intent-filter>必须全部包含Activity才能启动;

如果一个意图可以匹配多个ActivityAndroid系统会提示选择;

每个Intent中只能指定一个action,但却能指定多个category;类别越多,动作越具体,意图越明确 
在Intent添加类别可以添加多个类别,那就要求被匹配的组件必须同时满足这多个类别,才能匹配成功。操作Activity的时候,如果没有类别,须加上默认类别 
当Intent匹配成功的组件有多个时,显示优先级高的组件,如果优先级相同,显示列表让用户自己选择 
优先级从-1000至1000,并且其中一个必须为负的才有效 
注:系统默认的浏览器并没有做出优先级声明,其优先级默认为正数。

区别

显式启动:直接指定要跳转的Activity类名,不用过滤,效率高,适用于同一个应用中的不同Activity跳转
隐式启动:需要过滤,相对耗时,但可以找到所有之匹配的应用。适用于不同应用之间的Activity跳转。

Activity之间的数据传递

使用Intent.putExtra()方法装入一些数据, 被启动的Activity可在 onCreate方法中getIntent()获取;

可传输的数据类型: 1.基本数据类型(数组),  2. String(数组),  3. Bundle(Map),  4.Parcelab(推荐)  Serializable(Bean),

基本类型:

Intent intent = new Intent(this, OtherActivity.class);

intent.putExtra("name", "张飞"); // 携带数据

intent.putExtra("age", 12);

startActivity(intent);

一捆数据:

Intent intent = new Intent(this, OtherActivity.class);

Bundle b1 = new Bundle();

b1.putString("name", "赵云");

b1.putInt("age", 25);

intent.putExtra("b1", b1);

序列化对象(须实现序列化接口):

4、关闭时返回数据

基本流程:

使用startActivityForResult(Intent intent, int requestCode) 方法打开Activity

重写onActivityResult(int requestCode, int resultCode, Intent data) 方法;

Activity中调用setResult(int resultCode, Intent data) 设置返回数据之后,关闭Activity就会调用上面的onActivityResult方法;

onActivityResult()发生在onStart()之前

不要通过 Intent 在 Android 基础组件之间传递大数据(binder transaction 缓存为 1MB),可能导致 OOM

Activity与Fragment之间传值

第一种就是在activity中建一个bundle,把要传的值存入bundle,然后通过fragment的setArguments(bundle)传到fragment,在fragment中,用getArguments接收,

具体代码如下

     activity:

FragmentTransaction ft=fm.beginTransaction();
OneFragment oneFragment=new OneFragment();
ft.replace(R.id.frame,oneFragment,"f1");
Bundle bundle=new Bundle();
bundle.putString("dad","kkk");——这里的kkk就是要传的值
oneFragment.setArguments(bundle);
ft.commit();
下面是fragment代码
 
  
Bundle bundle=getArguments();
String s=bundle.getString("dad");
Log.e("kkkkkk",s);
 
  
第二种就是在activity中定义一个public的方法,将要传递的值以return的方式返回,在fragment的onAttach方法中,调用这个方法得到值
具体代码如下
activity:
//注意返回类型
 
  
public String rr(){
    return "lll";
}
 
  
fragment代码:
//这里s是一个全局的String类型变量 
@Override
public void onAttach(Context context) {
    super.onAttach(context);
    Log.i("fragment_111111111","onAttach");
    s=((MainActivity)context).rr();
}
/**
 * Activity传值到Fragment
 * 并接收从Fragment返回的值
 * @author James
 *
 */
public class MainActivity extends Activity {
    private Button btn_send;
    private MyFragment myFragment;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        btn_send = (Button)findViewById(R.id.button);
        
        FragmentManager manager = getFragmentManager();
        FragmentTransaction transation = manager.beginTransaction();
        myFragment = new MyFragment();
        transation.add(R.id.layout_container_fragment, myFragment);
        transation.commit();
        
        //Activity传值,通过Bundle
        Bundle bundle = new Bundle();
        bundle.putString("MainActivity", "Hello,Fragment");
        //首先有一个Fragment对象 调用这个对象的setArguments(bundle)传递数据
        myFragment.setArguments(bundle);
        
        //点击按钮接受Fragment传回来的值
        btn_send.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Bundle bundle = myFragment.getArguments();
                String result = bundle.getString("MyFragment");
                Toast.makeText(MainActivity.this, result, Toast.LENGTH_LONG).show();
            }
        });
    }
}

/**
 *@author James
 *@date 2016年7月12日
 *@Version 1.0
 */
public class MyFragment extends Fragment{
    private Button btn_fragment;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.activity_fragment, container, false);
        btn_fragment = (Button)view.findViewById(R.id.button_fragment);
        //点击按钮接收Activity传过来的值
        btn_fragment.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Bundle bundle = getArguments();
                String result = bundle.getString("MainActivity");
                Toast.makeText(getActivity(), result, Toast.LENGTH_LONG).show();
            }
        });
        
        //Fragment回传值给Activity
        getArguments().putString("MyFragment", "Hello,Activity");
        return view;
    }
}

也可通过RxJava或EventBus进行传递

猜你喜欢

转载自blog.csdn.net/weixin_41205419/article/details/79883720