Android Day06四大组件之Activity多页面跳转和数据传递

简介:





1.什么是Activity

  官方文档是这么说的:An Activity is an application component that provides a screen     with which users can interact in order to do something, such as dial the phone,     take a photo, send an email, or view a map. Each activity is given a window in     which to draw its user interface. The window typically fills the screen, but may be     smaller than the screen and float on top of other windows.  

   大致意思是说:Activity是一个应用程序组件,给用户提供一个屏幕让用户可以与之交互做一些事

   情。

2.Activity的生命周期

  下面这张图是官方文档提供的Activity的生命周期的图:

  wKioL1W1Bw_BKJpMAAGYF3aC11U539.jpg

  

  

   ·onCreate 方法    当Activity启动的是调用

    ·onDestroy方法    当Activity销毁的时候调用

    ·onStart 方法    当Activity可见的时候调用 

    ·onStop 方法     当Activity 不可见的时候调用 

    ·onResume 方法    当Activity上的按钮 获得焦点 可以被点击的时候调用 

    ·onPause 方法    当Activity 上的按钮 失去焦点 按钮不可以被点击的时候调用     

     ·onRestart 方法   当界面被重新加载的时候调用 注意这个方法


■手机按键对应的Activity生命周期的回调方法

    如果点击BACK键,会调用Activity的onPause()、onStop()、onDestroy()方法,Activity

  会注销掉。

    如果点击HOME键,会调用Activity的onPause()、onStop()方法,但不会执行onDestroy()   方法,程序会运行在后台。如果应用程序没有被系统杀死,那么再点击应用程序图标会调用Activity的onRestart()、onStart()、OnResume()方法。

■特殊的回调方法组合

  如果打开第一个Activity之后,不关闭它,开启另外一个Activity(非透明的),会调用第一个Activity的onPause()、onStop()方法。

    如果打开第一个Activity之后,不关闭它,开启另外一个Activity(透明的),会调用第一个

  Activity的onPause()方法,而不会去调用onStop()方法,因为第一个Activity还是可见的。如果关

  闭透明的Activity,第一个Activity只会回调onResume()方法。

■切屏对应的Activity生命周期的回调方法 

   手机在切屏的时候,会先销毁,再创建.走onPause()、onStop()、onDestroy()方法,再走onCreate

 ()、onStart()、onResume()方法。这一过程就相当于关闭并重新进入应用一样,那么如何防止手机

 在切屏时生命周期发生改变呢?

   第一种方式:把Activity页面的朝向写死,通过这个属性

    android:screenOrientation="portrait"  portrait代表竖屏  landscape代表横屏

    朝向写死,在手机上方向是不能改变的,但是在AVD上仍可以切屏,只是生命周期没有变化。

   第二种方式:android:configChanges="orientation|keyboardHidden|screenSize"

      

3.Activity的清单配置

  如果想让Activity成为应用程序的入口,需要将activity的意图过滤器配置如下:

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

   Android允许程序有多个activity作为应用程序的入口,只要activity配置了以上的意图过滤器,就会在手机桌面上创建多个应用程序图标,点击图标会进入对应的activity界面。


   如果activity节点没有设置自己的label和icon,会默认使用application节点的label和icon。


4.Activity的页面跳转及数据传递

  拓展:话说android Activity之间数据传递      http://blog.csdn.net/maylian7700/article/details/7323993

   注意的问题,序列化的类中还有自定义的类,则这个类也要序列化,否则会出错.

  ■启动Activity传数据和取数据

    本Activity:传数据,通过Intent对象的setData()和putExtra()方法封装数据至Intent对象。

    被调用的的Activity:取数据,通过Activity类的getIntent()方法先得到开启这个Activity的

               Intent对象,也就是本Activity里传数据用到的Intent对象,然后通过

               Intent对象的getXxxExtra()方法得到数据。

     

   ■启动Activity的2种方式

      第一种:不需要被启动的Activity返回数据

                startActivity(intent);

      第二种:需要被启动的Activity返回数据      

                startActivityForResult(intent, int类型的请求码);

    对于第二种Activity的启动方式,需要思考的两个问题?

     1)被调用的Activity怎么返回数据?

        首先,调用者Activity启动被调用的Activity的方式是

                    startActivityForResult(intent, int类型的请求码);

         其次,在被调用的Activity里面,创建Intent对象,将要返回的数据封装进Intent对

      象,调用Activity类的setResult(int resultCode, Intent data)方法返回Intent对象。

       如:  

1
2
3
4
             //将数据返回
         Intent intent =  new  Intent();
         intent.putExtra( "phone" , phone);
         setResult( 10 , intent);

     2)调用者Activity怎么获取被调用的Activity所返回的数据?   

         通过复写Activity的onActivityResult方法可以得到其它的一个或多个Activity返

       回的数据.

       如:

        wKioL1W5A87SAnYWAAFJ51EFJ9U696.jpg  

      上面的截图是Android官方文档的截图,利用了双重判断确定是哪个对象返回的数据,这样显

    得更加严密. 返回的数据就存储在方法中的参数data中,调用Intent对象的方法取出即可.

     

5.应用1_短信大全

    需求:将一些好的短信显示到ListView上,点击某一条短信,就跳到手机的短信发送页面,并把

       ListView选中条目的内容添加到短信发送页面的短信内容中.

    分析:这个需求首先涉及到ListView的使用,然后跳到手机短信发送页面,涉及到隐式意图启动系

       统应用,并且要将本应用的数据传递到系统应用里,涉及到页面跳转和数据传递.

     效果图:

      假如我点击了ListView短信列表的第2条短信,然后就跳转到短信发送页面

       wKioL1W6S0nRbkw8AAH-95F3Dgs400.jpg       

    核心代码:

      

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public  void  onItemClick(AdapterView<?> parent, View view,
                     int  position,  long  id) {
                 //得到点击的item对应的数据
                 String msg = objects[position];
                 
                 //利用隐式意图,跳转到短信发送页面。
                 //怎么写过滤条件,查源码。。。。
                  /* <intent-filter>
                    <action android:name="android.intent.action.SEND" />
                    <category android:name="android.intent.category.DEFAULT" />
                    <data android:mimeType="text/plain" />
                    </intent-filter>*/
                 Intent intent = new Intent();
                 //设置意图对象的过滤条件
                 intent.setAction("android.intent.action.SEND");
                 intent.addCategory("android.intent.category.DEFAULT");
                 intent.setType("text/plain");
                 //传递数据给短信发送器
                 intent.putExtra("sms_body", msg);
                 
                 /*
                  * 不小心用了setDataAndType(Uri.parse(msg),"text/plain");结果短信发送器的联系人处是data,发送内容什么也没有。
                  * */
                 startActivity(intent);
             }

    那么问题来了,上面意图对象的过滤条件传递数据格式我是怎么知道的呢?

     1)先打开Logcat,然后打开手机短信发送页面,会看到Locat上打印这样一行信息(如果没有

      打印任何信息,先安装一个自己的应用,然后重新打开系统的短信发送页面。):

      wKioL1W5dLCDgYU-AACHQV7bEeE138.jpg     2)然后去系统应用源码里找到短信发送应用Sms,在清单文件里找到ComposeMessageActivity

       的配置

       短信发送页面有很多的过滤器,都是用于发现不同格式数据的(用mimetype属性来约束),

      我们这里就只需要文本类型的数据,就选择mimetype为text/plain的进行过滤了。 

      wKioL1W5dujw8Z-AAAMI1HRKLFM737.jpg   

       知道了意图对象的过滤器,那么就可以为意图对象设置过滤信息

       3)但是,怎么给intent传递数据呢?那么就得看短信发送页面的Activity是如何获取调用

         它的Intent的数据的?

        通过在ComposeMessageActivity.java里搜索getStringExtra可以得到短信发送器是根据

        sms_body键名来获取短信内容的。

        wKiom1W6Ru2Ctqd9AAFHZ3wqJF4087.jpg

        所以Intent在putExtra时采用的键名是“sms_body”。

  

 6.应用2_短信发送器

    需求:做一个如下图所示的短信发送器,布局采用混合线性布局。

       功能1:在主UI界面中点击“添加联系人”那个+号按钮,就弹出一个窗体列出联系人(是

          模拟数据,学到内容提供者即可获取手机真正的联系人),选择一个联系人后关闭

          选择联系人页面,并将选择的联系人电话返回显示到主UI界面的文本框中。

       功能2:在主UI界面中点击“插入模板”按钮,就弹出一个窗体列出一些短信,选择一条

          短信后关闭短信大全页面,将将选择的短信返回显示到主UI界面的短信内容文本框

       wKiom1W6UkCB9uVQAAFR11_a11U635.jpg 

     分析:上面的需求,也涉及到页面跳转和数据传递,不同的是被调用的页面在关闭的同时还要

       向调用者(主UI界面)返回选择的数据。那么,这个应用要求的技术有以下几点:

       1)主UI界面在启动其它Activity的时候,应当使用startActivityForResult的方式,并

        复写Activity的onActivityResult方法。

       2)两个返回数据的ListView都要设置item点击事件,在事件中返回数据并关闭页面。

       3)发送短信的功能   

     核心代码:

       1)短信模板页面

        因为ListView只需显示单列数据,适配器就直接使用ArrayAdapter了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//模拟数据
         final  String[] objects = {短信内容,为节省空间就不写了。};    
         //得到 listview
         ListView lv_templates = (ListView) findViewById(R.id.lv_templates);
         //绑定lv的适配器,用ArrayAdapter。
         lv_templates.setAdapter( new  ArrayAdapter<String>( this , R.layout.item_activity_sms_template, R.id.item, objects));
         //注册lv的item点击事件
         //要实现的逻辑:获取数据,返回数据,关闭当前activity
         lv_templates.setOnItemClickListener( new  OnItemClickListener() {
 
             @Override
             public  void  onItemClick(AdapterView<?> parent, View view,
                     int  position,  long  id) {
                 //得到数据
                 String content = objects[position];
                 
                 //通过intent返回数据
                 Intent intent =  new  Intent();
                 intent.putExtra( "content" , content);
                 setResult( 20 , intent);
                 
                 //关闭当前activity
                 finish();
             }
         });

       2)选择联系人页面      

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
//模拟数据
final  List<Map<String, String >> lists =  new  ArrayList<Map<String, String >> ();
for ( int  i =  0  ; i <  20 ; i++)
{
     Map<String,String> map =  new  HashMap<String, String>();
     map.put( "name" , "联系人"  + i);
     map.put( "phone" , new  Random().nextInt( 252523 )+ "" );
     lists.add(map);
}
 
//得到 listview
ListView lv_contacts = (ListView) findViewById(R.id.lv_contacts);
 
//绑定lv的适配器,用SimpleAdapter,可以添加多个textview。  
lv_contacts.setAdapter( new  SimpleAdapter( this , lists, R.layout.item_activity_contacts, new  String[]{ "name" , "phone" },  new  int [] {R.id.tv_name,R.id.tv_phone}));
 
//注册lv的item点击事件
//要实现的逻辑:获取数据,返回数据,关闭当前activity
lv_contacts.setOnItemClickListener( new  OnItemClickListener() {
 
     @Override
     public  void  onItemClick(AdapterView<?> parent, View view,
             int  position,  long  id) {
         //拿到相应item的数据,通过lists集合,只要电话号码。
         String phone = lists.get(position).get( "phone" );
         
         //将数据返回
         Intent intent =  new  Intent();
         intent.putExtra( "phone" , phone);
         setResult( 10 , intent);
         
         //关闭当前activity
         finish();
     }
});

     3)主UI页面 

         获取模板页面和联系页面数据并显示

1
2
3
4
5
6
7
8
9
10
protected  void  onActivityResult( int  requestCode,  int  resultCode, Intent data) {
         //通过resultCode来区别不同的activity返回的intent对象 
         if (resultCode ==  10 )
         {
             et_name.setText(data.getStringExtra( "phone" ));
         }
         else  if  (resultCode ==  20 ){
             et_content.setText(data.getStringExtra( "content" ));
         }
     }

        发送短信

          通过SmsManager这个类,注意它的获取方式是通过SmsManager.getDefault方法

          与打电话不同,打电话是通过隐式意图来调用的。 


          记得要在清单文件里加上权限: 

            <uses-permission android:name="android.permission.SEND_SMS"/>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  public  void  send()
     {
         //TODO 短信发送
         //得到联系人和发送内容 
         String name = et_name.getText().toString().trim();
         String content = et_content.getText().toString().trim();
         
         //利用一个类SmsManager来发送短信      注意不要用过时的SmsManager
         SmsManager smsManager = SmsManager.getDefault();
         
         //短信内容过长,就得切割之后再一条条发送。
         ArrayList<String> divideMessage = smsManager.divideMessage(content);
         
         for (String msg : divideMessage)
         {
             smsManager.sendTextMessage(name,  null , msg,  null null );
         }
     }



7.Android中的任务栈  


    1. 栈 :先进后出  

    2. 队列  先进先出 

    3. 任务栈  :是用来维护Activity的  ,| Activity是用来维护用户的操作体验的

    4. 打开一Activity 叫 进栈 

    5. 关闭一个Activity 出栈  

    6. 我们用户操作的Activity 永远是栈顶的Activity

    7. 说我们应用程序退出了 实际上是任务栈清空了

    8. 一般情况下 一个应用程序对应一个任务栈 


8.Android中4种启动模式 

 1.android:launchMode="standard"(默认)

    wKioL1W6o12zRVkFAABq4U0bpMM250.jpg

  2.singletop 单一顶部模式 在activity的配置文件中设置android:launchMode="singleTop"

    如果任务栈的栈顶存在这个要开启的activity,不会重新的创建activity,而是复用已经存在

   的activity。保证栈顶Activity如果存在,不会重复创建。
    应用场景:浏览器的书签

    wKiom1W6oYDi9pYWAAB9jXtp0zk993.jpg

    

 3. singetask 单一任务栈,在当前任务栈里面只能有一个实例存在
    当开启activity的时候,就去检查在任务栈里面是否有实例已经存在,如果有实例存在就复用

   这个已经存在的activity,并且把这个activity上面的所有的别的activity都清空,复用这个已经

   存在的activity。保证整个任务栈里面一个Activity只有一个实例存在

     应用场景:浏览器的activity

    如果一个activity的创建需要占用大量的系统资源(cpu,内存)一般配置这个activity为

   singletask的启动模式。webkit内核 c代码

     wKioL1W6pFeD5Pd7AADodUQz2oc011.jpg 

  4.singleInstance启动模式非常特殊, activity会运行在自己的任务栈里面,并且这个任务栈里面

   只有一个实例存在
   如果你要保证一个activity在整个手机操作系统里面只有一个实例存在,使用singleInstance
   应用场景: 来电页面   有道词典

   wKioL1W6pTeiQRLBAACC2S7HrsQ416.jpg 

和Activity相关的其它技术点:

   1.当 Activity 以全屏模式运行时,如何允许 Android 系统状态栏在顶层出现,而不迫使 Activity 重新布局让

             出空间?

      http://www.zhihu.com/question/19760889




      本文转自屠夫章哥  51CTO博客,原文链接:http://blog.51cto.com/4259297/1678564,如需转载请自行联系原作者

相关文章
|
2月前
|
开发框架 前端开发 Android开发
Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势
本文深入探讨了 Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势。这对于实现高效的跨平台移动应用开发具有重要指导意义。
217 4
|
2月前
|
搜索推荐 Android开发 开发者
探索安卓开发中的自定义视图:打造个性化UI组件
【10月更文挑战第39天】在安卓开发的世界中,自定义视图是实现独特界面设计的关键。本文将引导你理解自定义视图的概念、创建流程,以及如何通过它们增强应用的用户体验。我们将从基础出发,逐步深入,最终让你能够自信地设计和实现专属的UI组件。
|
3月前
|
存储 Android开发 开发者
深入理解安卓应用开发的核心组件
【10月更文挑战第8天】探索Android应用开发的精髓,本文带你了解安卓核心组件的奥秘,包括Activity、Service、BroadcastReceiver和ContentProvider。我们将通过代码示例,揭示这些组件如何协同工作,构建出功能强大且响应迅速的应用程序。无论你是初学者还是资深开发者,这篇文章都将为你提供新的视角和深度知识。
|
3月前
|
数据可视化 Android开发 开发者
安卓应用开发中的自定义View组件
【10月更文挑战第5天】在安卓应用开发中,自定义View组件是提升用户交互体验的利器。本篇将深入探讨如何从零开始创建自定义View,包括设计理念、实现步骤以及性能优化技巧,帮助开发者打造流畅且富有创意的用户界面。
116 0
|
1月前
|
XML 搜索推荐 前端开发
安卓开发中的自定义视图:打造个性化UI组件
在安卓应用开发中,自定义视图是一种强大的工具,它允许开发者创造独一无二的用户界面元素,从而提升应用的外观和用户体验。本文将通过一个简单的自定义视图示例,引导你了解如何在安卓项目中实现自定义组件,并探讨其背后的技术原理。我们将从基础的View类讲起,逐步深入到绘图、事件处理以及性能优化等方面。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的见解和技巧。
|
3月前
|
Android开发
Android面试之Activity启动流程简述
Android面试之Activity启动流程简述
99 6
|
3月前
|
消息中间件 Android开发 索引
Android面试高频知识点(4) 详解Activity的启动流程
Android面试高频知识点(4) 详解Activity的启动流程
34 3
|
3月前
|
缓存 前端开发 Android开发
Android实战之如何截取Activity或者Fragment的内容?
本文首发于公众号“AntDream”,介绍了如何在Android中截取Activity或Fragment的屏幕内容并保存为图片。包括截取整个Activity、特定控件或区域的方法,以及处理包含RecyclerView的复杂情况。
32 3
|
3月前
|
XML 前端开发 Java
安卓应用开发中的自定义View组件
【10月更文挑战第5天】自定义View是安卓应用开发的一块基石,它为开发者提供了无限的可能。通过掌握其原理和实现方法,可以创造出既美观又实用的用户界面。本文将引导你了解自定义View的创建过程,包括绘制技巧、事件处理以及性能优化等关键步骤。
|
3月前
|
测试技术 数据库 Android开发
深入解析Android架构组件——Jetpack的使用与实践
本文旨在探讨谷歌推出的Android架构组件——Jetpack,在现代Android开发中的应用。Jetpack作为一系列库和工具的集合,旨在帮助开发者更轻松地编写出健壮、可维护且性能优异的应用。通过详细解析各个组件如Lifecycle、ViewModel、LiveData等,我们将了解其原理和使用场景,并结合实例展示如何在实际项目中应用这些组件,提升开发效率和应用质量。
57 6