zoukankan      html  css  js  c++  java
  • Android基础总结(2)——活动Activity

    1、什么是活动(Activity)

      活动(Activity)是一种可以包含用户界面的组件,主要用于和用户进行交互。一个应用程序中可以包含零个或多个活动,但不包含任何活动的应用程序很少见。

    2、怎么使用活动(Activity)

    定义Activity:

    1 public class MainActivity extends Activity {
    2 
    3     @Override
    4     protected void onCreate(Bundle savedInstanceState) {
    5         super.onCreate(savedInstanceState);
    6         setContentView(R.layout.activity_main);
    7     }
    8 
    9

    注册Activity:

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     3     package="com.example.example"
     4     android:versionCode="1"
     5     android:versionName="1.0" >
     6 
     7     <uses-sdk
     8         android:minSdkVersion="14"
     9         android:targetSdkVersion="22" />
    10 
    11     <application
    12         android:allowBackup="true"
    13         android:icon="@drawable/ic_launcher"
    14         android:label="@string/app_name"
    15         android:theme="@style/AppTheme" >
    16         <activity
    17             android:name=".MainActivity"
    18             android:label="@string/app_name" >
    19             <intent-filter>
    20                 <action android:name="android.intent.action.MAIN" />
    21 
    22                 <category android:name="android.intent.category.LAUNCHER" />
    23             </intent-filter>
    24         </activity>
    25     </application>
    26 
    27 </manifest>
    • 我们创建的任何活动都应该继承自Activity类,然后必须重写其中的onCreate(Bundle savedInstanceState)方法
    • Android程序的设计讲究数据逻辑和视图分开,所以最好每一个活动都对应一个布局,布局就是用来显示界面内容的。一般在重写的onCreate(Bundle savedInstanceState)方法中用setContentView(R.layout.activity_main)方法来给当前活动加载一个布局,在setContentView()中我们一般是传入相应布局文件的id,所以写法是R.layout.activity_main。注意:这里的R文件是我们项目目录下的R.java文件,Android SDK还会自动提供一个android包下的R文件,这两个是不同的,不要弄混了。
    • 所有的活动都需要在AndroidManifest.xml中进行注册才能生效。

    3、在活动使用Toast

      Toast是Android系统提供的一种非常好的提醒方式,在程序中可以使用它将一些短小的信息通知给用户,这些信息会在一段时间后自动消失,并且不占用任何屏幕空间。其原型是

      public static Toast makeText(Context context, CharSequence text, @Duration int duration)  ;使用方法一般是:

    Toast.makeText(MainActivity.this, "notify string", Toast.LENGTH_SHORT).show() ;

    4、在活动中使用Menu

    • 通过在res/menu目录下创建相关菜单的xml文件,
    • 然后在对应的Activity中先重写 onCreateOptionsMenu(Menu menu)方法创建菜单,在该方法中通过getMenuInflater()方法能够得到MenuInflater对象,然后调用其inflate()方法就可以在当前活动中创建菜单了。 inflate(int menuRes, Menu menu)中传入两个参数:
      • 第一个参数是指定我们通过哪一个资源文件来创建菜单,传入的就是res/menu目录下对应的xml文件,这里当然就是R.menu.main
      • 第二个参数是用于指定我们的菜单项将添加到哪一个Menu对象中去,这里直接使用传入的menu参数即可,然后返回true,bison允许创建的菜单显示出来,如果返回false,创建的菜单将无法显示
    • 最后,我们需要重写 onOptionsItemSelected(MenuItem item) 方法,在该方法中定义点击不同的菜单选项的响应效果。

    res/menu目录下创建的菜单布局:main.xml

     1 <menu xmlns:android="http://schemas.android.com/apk/res/android"
     2     xmlns:tools="http://schemas.android.com/tools"
     3     tools:context="com.example.example.MainActivity" >
     4 
     5     <item
     6         android:id="@+id/add_item"
     7         android:title="Add"/>
     8 
     9        <item
    10         android:id="@+id/remove_item"
    11         android:title="Remove"/>
    12     
    13 </menu>

    重写onCreateOptionsMenu(Menu menu)方法创建菜单:

    1 @Override
    2     public boolean onCreateOptionsMenu(Menu menu) {
    3         // Inflate the menu; this adds items to the action bar if it is present.
    4         getMenuInflater().inflate(R.menu.main, menu);
    5         return true;
    6     }

    重写 onOptionsItemSelected(MenuItem item) 方法各定义菜单项的响应:

     1 @Override
     2 public boolean onOptionsItemSelected(MenuItem item) {
     3     // Handle action bar item clicks here. The action bar will
     4     // automatically handle clicks on the Home/Up button, so long
     5     // as you specify a parent activity in AndroidManifest.xml.
     6     int id = item.getItemId();
     7     switch(id){
     8     case R.id.add_item :
     9         Toast.makeText(this, "ADD", Toast.LENGTH_SHORT).show();
    10         break ;
    11     case R.id.remove_item :
    12         Toast.makeText(this, "REMOVE", Toast.LENGTH_SHORT).show();
    13         break ;
    14     default:
    15     }
    16     
    17     return true ;
    18 }

    5、销毁一个活动

    直接调用Activity类的finish()方法就可以销毁当前活动。

    6、多个活动之间的互相启动纽带:Intent

      在Adroid中,多个活动之间互相启动通过Intent来实现。Intent是Android程序中各组件之间进行交互的一种重要方式,它不仅可以指明当前组件想要执行的动作,还可以在不同组件之间传递数据。Intent的构造方法有多种,比较常用的是通过Intent(Context packageContext, Class<?> cls)来连接各组件进行交互。

      

      Intent具体用法大致分为两种:使用显示Intent和使用隐式Intent

      • 显式Intent在创建Intent对象时明确指出我们想要启动的组件对象。首先通过Intent(Context packageContext, Class<?> cls)来显示地连接当前组件所在的Context和另一个组件的class文件,然后通过Activity类中的startActivity(Intent internet)方法来启动目标组件。
        1 button.setOnClickListener(new OnClickListener() {                        
        2      @Override
        3      public void onClick(View v) {
        4         Intent intent = new Intent(MainActivity.this, SecondActivity.class) ;
        5          startActivity(intent) ;  
        6      }
        7  });
      • 隐式Intent:相比显式Intent,比较含蓄,不会明确指出想要启动的组件。而是指定了一系列更为抽象的action和category 等信息,然后交由系统去分析这个Intent,并帮我们找出合适的组件去执行启动。具体方法是首先通过在AndroidManifest.xml文件中的<activity>标签下配置<intent-filter>的内容,可以指定当前活动能够响应的action和category。然后我们使用Intent(String action)构造函数将action的字符串传进去,表明我们想要启动能够响应相应action类型的组件。
        • 注意:只有<action>和<category>中的内容同时匹配上Intent中指定的的action和category时,这个组件才能响应Intent。
        • 而且每一个Intent中只能指定一个action,但是可以指定多个category,通过Intent的addCategory()方法来添加category种类。当然,增加category种类之后,响应该Intent的组件也必须同时满足action和多个category的标签
        • 还有一点要注意的是android.intent.category.DEFAULT是默认的category,在调用startActivity()方法时,系统会自动添加到Intent的种类筛选中去
           1 <activity
           2     android:name=".SecondActivity"
           3     android:label="@string/title_activity_second" >
           4 
           5     <intent-filter>
           6         <action android:name="com.example.activitytest.ACTION_START" />
           7 
           8         <category android:name="android.intent.category.DEFAULT" />
           9     </intent-filter>
          10 
          11 </activity>
          1 button.setOnClickListener(new OnClickListener() {                        
          2     @Override
          3     public void onClick(View v) {
          4         Intent intent = new Intent("com.example.activitytest.ACTION_START") ;
          5         //添加category的种类
          6         intent.addCategory("com.example.activitytest.MY_CATEGORY") ;
          7         startActivity(intent) ;
          8     }
          9 });
      • 更多隐式Intent的用法:使用隐式Intent不仅能够启动自己程序中的活动,还可以启动其他程序中的活动,这使得Android多个应用程序之间的功能共享成为了可能。我们也可以通过其他构造函数,指定uri或setData()方法设置uri的方法来实现隐式Intent的功能。当一个Intent对象被一个intent-filter进行匹配测试时,只有三个方面会被参考到:动作、数据 (URI以及数据类型)和类别。详情可参考:http://blog.csdn.net/hunanwy/article/details/8622433  或者 《第一行代码:Android》  P46

    6、如何向下一个活动传递数据以及返回数据给上一个活动

      在启动活动时传递数据的思路很简单,Intent中提供了一系列putExtra()方法的重载,可以将我们想要的数据暂存在Intent中,启动另一个活动后,只需要将这些数据取出就可以了。

       例如我们在mainActivity中的button中设置点击事件的监听事件中,启动Intent之前通过putExtra()方法传入各种类型的数据,

     1 button.setOnClickListener(new OnClickListener() {                        
     2             @Override
     3             public void onClick(View v) {
     4                 Intent intent = new Intent(MainActivity.this, SecondActivity.class) ;
     5                 intent.putExtra("str", "this is main activity") ;
     6                 intent.putExtra("int", 32) ;
     7                 startActivity(intent) ;
     8                 
     9             }
    10         });

       然后我们启动的另一个活动中同样通过Intent的get方法取出对应名字的数据,一般get方法有两个参数,第一个是字符串,是我们查找对应参数的标准,第二个参数是如果没有对应的值则取得默认值。

     1 @Override
     2     protected void onCreate(Bundle savedInstanceState) {
     3         super.onCreate(savedInstanceState);
     4         setContentView(R.layout.activity_second);
     5         
     6         Intent intent = getIntent() ;
     7         String str = intent.getStringExtra("str") ;
     8         int i = intent.getIntExtra("int", -1);
     9         System.out.println(str + i);
    10     }

     返回数据给上一个活动

    1. 如果要返回数据给上一个活动,则用startActivityForResult()方法来启动费另一个活动,该方法接收两个参数,第一个是Intent,第二个是请求码,用于在之后的回调中判断数据的来源,该请求码只要是一个唯一值就可以了。
      1 button.setOnClickListener(new OnClickListener() {                        
      2             @Override
      3             public void onClick(View v) {
      4                 Intent intent = new Intent(MainActivity.this, SecondActivity.class) ;
      5                 intent.putExtra("str", "this is main activity") ;
      6                 startActivityForResult(intent, 1);
      7                 
      8             }
      9         });
    2. 然后我们在SecondActivity中处理完之后,将返回的数据通过putExtra()方法写入Intent,并调用setResult()方法进行返回intent便于第一个活动处理,setResult()方法也是两个参数,第一个是参数用于向上一个活动返回处理结果,一般只用RETURN_OK或RETURN_CANCELED这两个值。
       1 button2.setOnClickListener(new OnClickListener() {
       2             
       3             @Override
       4             public void onClick(View v) {
       5                 Intent intent = new Intent() ;
       6                 intent.putExtra("data_return", "hello, i am the secondActivity") ;
       7                 setResult(RESULT_OK, intent) ;
       8                 
       9             }
      10         });
    3. SecondActivity被销毁之后会回调上一个活动的onActivityResult()方法,因此我们还需要在第一个活动中重写onActivityResult()方法,在该方法中我们对返回的数据和结果进行处理。
       1 @Override
       2     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
       3         switch(requestCode){
       4         case 1:
       5             if(resultCode == RESULT_OK){
       6                 String returnData = data.getStringExtra("data_return") ;
       7                 Log.d("mainActivity", returnData) ;
       8             }
       9             break ;
      10         default:
      11                 
      12         }
      13     }

     7、活动的生命周期

      Android是使用任务栈(Task)来管理活动的,一个任务就是一组存放在栈中的活动的集合,这个栈也被称作返回栈。每当我们开启一个新的活动,它会在返回栈中入栈,并处于栈顶的位置;而每当我们按下Back键或调用finish()方法去销毁一个活动时,处于栈顶的活动会出栈,这时前一个入栈的活动就会重新回到栈顶的位置。系统总是显示处于栈顶位置的活动给用户

    每个活动在其生命周期汇总最多可能有四种状态

    • 运行状态:当一个活动处于栈顶位置,系统最不愿回收的就是处于运行状态下的活动
    • 暂停状态:当一个活动不再处于栈顶位置,但是仍然可见。(因为并不是每一个活动都会布满屏幕,例如Toast等出现时,前一个活动就是暂停状态),该状态下的活动仍然是完全存活的,系统也不愿意去回收
    • 停止状态:当一个活动不再处于栈顶位置,并且完全不可见时,系统愿意为这种活动保存相应的状态和变量,但是不完全可靠,当其他地方需要内存时,有可能被回收。
    • 销毁状态:当一个活动从回收栈中移除后就变成了销毁状态。

    Activity生命周期图

    activity的七个回调方法

    • onCreate():当Activity第一次被实例化的时候系统会调用,整个生命周期只调用1次这个方法。通常用于初始化设置,为Activity设置所要使用的布局文件,为按钮绑定监听器等静态的设置操作。
    • onStart():当Activity可见未获得用户焦点不能交互时系统会调用。由不可见变为可见时调用。
    • onRestart():当Activity已经停止然后重新被启动时系统会调用。
    • onResume():当Activity可见且获得用户焦点交互时系统会调用。此时的活动一定位于返回栈栈顶,并且处于运行状态。
    • onPause():在系统准备去启动或恢复另一个活动的时候调用。我们通常在这里会将一些消耗CPU的资源释放掉,并在这里保存你的一些关键数据,因为这个时候你的程序的优先级降低,有可能被系统收回。
    • onStop():在活动完全不可见的时候调用。
    • onDestroy():当Activity(用户调用finish()或系统由于内存不足)被系统销毁杀掉时系统调用,(整个生命周期只调用1次)用来释放onCreate()方法中创建的资源,如结束线程等。

    android三个嵌套循环

    1. Activity的完整生命周期:从第一次调用onCreate()开始直到调用onDestroy()结束。一般情况下在onCreat()中完成各种初始化的操作,在onDestroy()中完成释放内存的操作。
    2. Activity的可视生命周期:从调用onStart()到相应的调用onStop()。在此生命期中,活动总是可见的。在这两个方法之间,可以保持显示Activity所需要的资源。如在onStart()中注册一个广播接收者监听影响你的UI的改变,在onStop()中注销。我们通过这两个方法合理地管理那些对用户可见的资源,比如在onStart()中对资源进行加载,在onStop()中进行释放。
    3. Activity的前台生命周期:从调用onResume()到相应的调用onPause()。在此生命期中,活动总是处于运行状态下的,此时的活动是可以和用户进行交互的。

    8、如何保存活动的状态?

      onSaveInstance的详情可以参见:http://blog.sina.com.cn/s/blog_618199e60101g1k5.html

      当一个活动被回收之后,我们该怎么去保存之前的状态呢?例如:我们希望之前在一个文本框中输入了数据,希望下次打开时仍然保持该数据。这时我们需要用到Activity中的另一个回调函数onSaveInstanceState(),在该方法中,接收一个Bundle对象,然后利用该对象的put方法将各种数据保存在Bundle对象中,然后在Activity的onCreate()方法(也是接收一个Bundle对象)中进行恢复,取出方法和Intent的保存和取出方法类似。

      Intent还可以和Bundle一起用于传递数据,首先可以把需要传递的数据保存在Bundle对象中,然后将Bundle对象存入Intent中,到了目标活动之后先从Intent中取出Bundle,再从Bundle中将后数据一一取出。

      onSaveInstanceState是用来保存UI状态的,你可以使用它保存你所想保存的东西,在Activity杀死之前,它一般在onStop或者onPause之前触发,onRestoreInstanceState则是在onResume之前触发回复状态,至于复写这个方法后onCreate方法是否会被调用。
      1.Activity被杀死了,onCreate会被调用,且onRestoreInstanceState 在 onResume之前恢复上次保存的信息。
      2.Activity没被杀死,onCreate不会被调用,但onRestoreInstanceState 仍然会被调用,在 onResume之前恢复上次保存的信息。
        onSaveInstanceState和onRestoreInstanceState 是一对兄弟,一个负责存储,一个负责取出.“不一定”是成对的被调用的。

       Activity的 onSaveInstanceState()onRestoreInstanceState()并不是生命周期方法,它们不同于 onCreate()、onPause()等生命周期方法,它们并不一定会被触发。当应用遇到意外情况(如:内存不足、用户直接按Home键)由系统销毁一个Activity时,onSaveInstanceState() 会被调用。但是当用户主动去销毁一个Activity时,例如在应用中按返回键,onSaveInstanceState()就不会被调用。因为在这种情况下,用户的行为决定了不需要保存Activity的状态。通常onSaveInstanceState()只适合用于保存一些临时性的状态,而onPause()适合用于数据的持久化保存。

      

    9、活动的启动模式:4种

    • standard:这是默认的启动模式。系统不在乎这个活动是否已经在返回栈中存在,每次启动都会创建该活动的一个新的实例。
    • singleTop:在启动活动时如果发现返回栈的栈顶已经是该活动了,则认为可以直接使用它,不用再创建新的活动实例。
    • singleTask:确保返回栈中活动不重复。每次启动活动时系统首先会在返回栈中检查是否存在该活动的实例,如果发现已经存在则直接使用,并把在这个活动之上的所有活动统统出栈,如果没有发现就会创建一个新的活动实例。
    • singleInstance:该模式下会启用一个新的返回栈来管理这个活动。(例如我们想实现其他程序和我们的程序可以共享一个活动,则应该用该模式启动活动)。

      注意:设置活动的启动方式是在AndroidManifest.xml文件中注册活动时,添加android:launchMode="singleTask"语句指明启动模式

     1 <activity
     2             android:name=".SecondActivity"
     3             android:launchMode="singleTask"
     4             android:label="@string/title_activity_second" >
     5             <intent-filter>
     6                 <action android:name="com.example.activitytest.ACTION_START" />
     7 
     8                 <category android:name="android.intent.category.DEFAULT" />
     9             </intent-filter>
    10         </activity>
  • 相关阅读:
    确保EF上下文线程内唯一
    linq的join
    编码:隐匿在计算机软硬件背后的语言
    EF删除数据
    插入数据返回主键值用 output inserted.UId
    Fancybox丰富的弹出层效果
    回车登录
    “:Choose a destination with a supported architecture in order to run on this device.”
    How to Enable Multi-Touch
    How does CCFileUTils::fullPathForFilename work
  • 原文地址:https://www.cnblogs.com/mukekeheart/p/5679179.html
Copyright © 2011-2022 走看看