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开发
[Android 四大组件] --- BroadcastReceiver
[Android 四大组件] --- BroadcastReceiver
33 0
|
4天前
|
Android开发 开发者
Android网络和数据交互: 请解释Android中的AsyncTask的作用。
Android&#39;s AsyncTask simplifies asynchronous tasks for brief background work, bridging UI and worker threads. It involves execute() for starting tasks, doInBackground() for background execution, publishProgress() for progress updates, and onPostExecute() for returning results to the main thread.
5 0
|
4天前
|
网络协议 安全 API
Android网络和数据交互: 什么是HTTP和HTTPS?在Android中如何进行网络请求?
HTTP和HTTPS是网络数据传输协议,HTTP基于TCP/IP,简单快速,HTTPS则是加密的HTTP,确保数据安全。在Android中,过去常用HttpURLConnection和HttpClient,但HttpClient自Android 6.0起被移除。现在推荐使用支持TLS、流式上传下载、超时配置等特性的HttpsURLConnection进行网络请求。
5 0
|
8天前
|
存储 数据库 Android开发
构建高效安卓应用:采用Jetpack架构组件优化用户体验
【4月更文挑战第12天】 在当今快速发展的数字时代,Android 应用程序的流畅性与响应速度对用户满意度至关重要。为提高应用性能并降低维护成本,开发者需寻求先进的技术解决方案。本文将探讨如何利用 Android Jetpack 中的架构组件 — 如 LiveData、ViewModel 和 Room — 来构建高质量的安卓应用。通过具体实施案例分析,我们将展示这些组件如何协同工作以实现数据持久化、界面与逻辑分离,以及确保数据的即时更新,从而优化用户体验并提升应用的可维护性和可测试性。
|
17天前
|
XML Java Android开发
Android每点击一次按钮就添加一条数据
Android每点击一次按钮就添加一条数据
21 1
|
1月前
|
存储 Android开发 C++
【Android 从入门到出门】第五章:使用DataStore存储数据和测试
【Android 从入门到出门】第五章:使用DataStore存储数据和测试
30 3
|
2月前
|
JavaScript Java 数据安全/隐私保护
安卓逆向 -- POST数据解密
安卓逆向 -- POST数据解密
25 2
|
2月前
|
数据可视化 Android开发
[Android 四大组件] --- Service
[Android 四大组件] --- Service
24 0
|
2月前
|
Android开发
[Android 四大组件] --- Activity
[Android 四大组件] --- Activity
22 1
|
2月前
|
存储 数据库 Android开发
安卓四大组件是什么?
安卓四大组件是什么?