探究活动-Activity

来源:互联网 发布:清与贝加尔湖知乎 编辑:程序博客网 时间:2024/05/16 11:35

探究Android Activity

1、活动是什么

        Activity是最容易吸引  用户 的东西

        Activiy是一种包含 用户界面的组件

        主要用于和用户进行交互

        一个application可以包含零个或多个活动


2、活动的基本用法(1-3与活动相关,4介绍Toast,5介绍Menu,6介绍一种活动销毁方式)

        手动创建 Android 项目
                      Android Studio 在一个工作区间内只允许打开一个项目
                      关闭当前项目 File->Close Project
                      新建Android 项目
                      ->Add NoActivity
                      click Finish->等待Gradle构建项目
                     
                      Ps:此时只是构建完项目 没有创建Activity 既没有布局(layout)也没有在AndroidManifest.xml中注册Activity

       1、手动创建活动Activity  

               首先更改项目结构  Android模式->Project模式
               com.eample.administrator.activitytest(Activity所在的包)->New->Activity->Empty Activity
               不勾选Generate Layout File 和 Launcher Activity:
                                                                                              Generate Layout File会自动为Activity创建一个相应的布局文件
                                                                                              Launcher Activity会自动将Activity设置为当前项目的主活动(可以在AndroidManifest.xml中单独设置)
              勾选Backwards Compatibility 表示会为项目启用 向下兼容 的模式 ->完成

              项目中的任何活动都要重写 Activity 的 onCreate() 方法
              Android Studio会自动完成简单的onCreate() 方法重写,里面添加 父类onCreate() 方法的调用:
                                  public class FirstActivity extends AppCompatActivity {
                                           
                                        @Override
                                        protected void onCreate(Bundle savedInstance) {
                                              super.onCreate(savedInstance);
                                        }
                                   }

       2、创建和加载布局

               Android程序讲究 逻辑 和 视图 分离。最好一个活动对应一个布局
               布局用来显示界面内容

              创建布局文件:
                                     app/src/main/res ->New->Directory 创建一个名为layout的目录
                                     layout->New->Layout resource file  创建一个名为first_layout的布局文件。根元素默认LinearLayout


              布局编辑器:
                                  Desin:
                                             可视化布局编辑器
                                             可以预览当前布局还可以通过拖放的方式编辑布局
                                  Text:
                                            通过XML文件的方式来编辑布局
              
              通过XML在布局文件中添加按钮:
                                
                                <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                                       android:orientation="vertical"
                                       android:layout_width="match_parent"
                                       android:layout_height="match_parent"
                 
                                <Button
                                         android:id=“@+id/button_1"
                                         android:layout_width="match_parent"
                                         android:layout_width="wrap_content"
                                         android:text="Button 1"
                                         />
                                </LinearLayout>

            android:id 是给当前元素定义一个唯一标识符
            Ps:@xx/xxxx是在XML中引用资源的方法   @+xx/xxxx实在XML中定义一个属性的方法

            android:layout_width是指定当前元素的宽度
            android:layout_height是指定当前元素的高度
            match_parent表示与父元素一样宽/高
            wrap_content表示当前元素的高度/宽度刚好包含里面的内容
            android:text指定了元素中显示的文字内容
            LinearLayout 表示线性布局
            android:orientation="vertical"垂直线性布局,"horizontal"水平线性布局
            

            加载布局:
                            在FirstActivity中 onCreate()方法中加入setContentView(R.layout.first_layout);
 
                            setContentView()方法需要一个参数-布局文件的id-R.layout.first_layout


             关于R.layout.first_layout:
                           项目中添加的任何资源都会在R文件中生成一个相应的    资源id   !资源!id!
                           所以创建的first_layout.xml布局的id被自动添加到R文件中
                           所以可以直接在方法中引用布局的id

    

    3、在AndroidManifest.xml文件中注册

           所有活动都要在AndroidManifest.xml中进行注册才能生效
           Android Studio一般会自动帮我们在AndroidManifest.xml中注册号Activity

           注册Activity:
                                在<activity>标签内注册
                                <activity android:name=".FirstActivity"></activity>
                               android:name 指定注册的活动
                                .FirstActivity 实际是com.example.administrator.activitytest.FirstActivity的缩写 因为:
                                   AndroidManifest.xml文件最外层标签<manifet>标签中已经通过package属性指定了程序的包名com.example.adminstrator.activitytest

                              配置主活动:
                                                  主活动就是程序运行起来时首先启动的活动
                                                  <activity>标签中加入<intent-filter>标签 具体如下:
                                                                  <activity android:name=".FirstActivity"
                                                                                android:label="This is FirstActivity">
                                                                          <intent-filter>
                                                                                      <action android:name="android.intent.action.MAIN"/>
                                                                                      <category android:name="android.intent.category.LAUNCHER"/>
                                                                          </intent-filter>
                                                                 </activity>
              
 
          
             android:label指定活动中标题栏内容 使用方法见上方代码
             标题栏是显示在活动最顶部的
             给   主活动   指定的 label 还会成为启动器(Launcher)中应用程序显示的名称


             如果没有给application声明主活动,那么该application可以正常安装,只是无法再Launcher中看到或者打开这个程序。
             这种application一般作为第三方服务供其他应用在内部调用



     4、在活动中使用Toast

            Toast是Android系统提供的一种 提醒方式
            通知用户短小信息
            短时间自动消失
            不占用任何屏幕空间
 
            Toast使用:
                             定义弹出Toast的触发点:在onCreate()方法中
                                    protected void onCreate(Bundel savedInstanceState) {
                                         super.onCreate(savedInstanceState);
                                         setContentView(R.id.first_layout);
                                         Button button1 = (Button) findeViewById(R.id.button_1);
                                         button1.setOnclickListener(new View.OnClickListener() {
                                              @Override
                                              public void onClick(View v) {
                                                      Toast.makeText(FirstActivity.this, "You clicked Button 1", Toast.LENGTH_SHORT).show();
                                               }
                                          });
                                     }

                              
                                     findViewById()方法获取布局文件中定义的元素(此处是R.id.button_1)
                                     findeViewById()方法获取的是一个View对象,向下转型为Button对象
                                     调用setOnclickListener()为按钮注册监听器
                                     实现一个匿名内部监听类
                                     在监听类的onClick()方法中实现弹出Toast:
         
                                                         静态方法makeText()创建一个Toast对象,调用show()将Toast显示出来
                                                         makeText()的三个参数:
                                                                   第一个Context:Toast要求的上下文,由于活动本身就是一个Context对象,这里直接传入FirstActivity.this
                                                                   第二个是Toast显示的文本内容
                                                                   第三个是Toast显示的时长,有两个内置常量Toast.LENGTH_SHORT和Toast.LENGTH_LONG

    5、在活动中使用Menu


           菜单项创建:
                    Android提供一种方式,让菜单能得到展示的同时不占用任何屏幕空间
          

                    Menu创建:
                                       res目录下创建一个menu文件夹:res目录->New->Directory->输入文件名menu->OK
                                       在menu文件夹下信件一个叫main的菜单文件:menu目录->New->Menu resource file->输入文件名main->OK
 
                     main.xml:
                                       <menu xmln:android="http://schemas.android.com/apk/res/android">
                                                   <item
                                                            android:id="@+id/add_item"
                                                            android:title="Add"/>
                                                  <item
                                                            android:id=:@+id/remove_item"
                                                            android:title="Remove"/>
                                       </menu>

                     <item>标签创建具体菜单项,android:id给出唯一标识符,android:title给这个菜单项指定名称

                     在FirstActivity中覆写onCreateOptionsMenu()方法(可使用Ctrl+O快捷键):
                  
                               public boolean onCreatOptionMenu(Menu menu) {
                                     getMenuInflater().inflate(R.menu.main, menu);
                                     return true;
                                }

                     getMenuInflater()得到MenuInflater对象
                     调用MenuInflater的inflate()方法创建菜单。
                     inflate()两个参数:
                                   第一个参数用于指定通过那个资源文件来创建菜单
                                   第二个指定我们的菜单项将添加到那个Menu对象中
                     返回值true表示允许创建的菜单显示出来,false表示无法显示

           菜单功能创建:
                     在FirstActivity中覆写onOptionsItemSelected()方法:
                                public boolean onOptionsItemSelected(MenuItem item) {
                                     switch (item.getItemId()) {
                                     case R.id.add_item:
                                             Toast.makeText(this, "You clicked Add", Toast.LENGTH_SHORT).show();
                                             break;
                                     case R.id.remove_item:
                                              Toast.makeText(this, "Yout clicked Remove", Toast.LENGTH_SHORT).show();
                                              break;
                                      default:
                                      }
                                      return true;
                                 }
               
                       在onOptionsItemSelected()方法中通过item.getItemId() 判断点击的菜单项

   6、销毁一个活动

          Back键可以销毁当前活动
          在活动中调用finish()方法也可以销毁当前活动,效果与Back一样


3、使用Intent在活动中穿梭

        活动之间的跳转与数据的传输
        Intent大致分为两种:显式Intent和隐式Intent

       1、使用显式Intent

              Intent有多个构造函数的重载
             构造函数:Intent(Context packageContext, Class<?>cls):
                                                   第一个参数Context指启动活动的上下文,比如FirstActivity.this
                                                   第二个参数Class是指想要启动的目标活动,比如SecondActivity.class
              Intent的使用:
                                  startActivity(intent):intent是先构造完成的Intent对象
                                  Activty类中的方法:startActivity()方法
              具体代码:
                            public void onClick(View v) {
                                     Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
                                     startActivity(intent);
                            }
              以上就实现了由FirstActivity跳转到SecondeActivity的功能

      2、使用隐式Intent

             不明确指定要启动哪一个活动

              隐式Intent的本质是通过XxxxActivity.java文件中的Intent对象所携带的action与category等与清单文件AndroidManifest.xml中
                    <intent-filter>标签里的<action>、<category>等相匹配来决定哪些活动能响应.java文件中的Intent对象
              Ps:另有博客讲述隐式Intent匹配原则。


              AndroidManifest.xml代码如下:
                        <activity android:name=".SecondeActivity">
                              <intent-filter>
                                     <action android:name="com.example.activitytest.ACTION_START" />
                                    <category android:name="android.intent.categoty.DEFAULT"/>
                             </intent-filter>
                        </activity>
 
               FirstActivity中按钮点击事件代码:
                       button1.setOnclickListener(new View.OnClickListener() {
                             @Override
                             public void onClick(View v) {
                                   Intent intent = new Intent("com.example.activitytest.ACTION_START");
                                   startActivity(intent);
                            }
                       });
     
            另一种Intent构造函数
            android.intent.category.DEFAULT是Intent的默认category,在调用startActivity()时会自动加入这个category
            每个Intent只能指定一个action,能指定多个category


     3、更多隐式Intent用法

            使用隐式Intent不仅可以启动自己程序内的活动,还可以启动其他程序的活动
            这帮助Android实现了多应用之间的功能共享

            应用程序中展示一个网页:
                 FristActivity按钮点击事件onClick中代码:
                       public void onClick(View v) {
                               Intent intent = new Intent(Intent.ACTION_VIEW);
                               intent.setData(Uri.parse("http://www.baidu.com"));  这是关键部分
                               startActivity(intent);
                       }

                指定Intent的action是Intent.ACTION_VIEW,只是一个Android系统内置动作,其常量值为android.intent.action.VIEW
                Uri.parse()方法把字符串解析为Uri对象
                setData方法接收Uri对象
     
         在<intent-filter>标签中再配置<data>标签,用于更精确的指定当前活动能够响应什么类型的数据
         <data>标签中主要配置以下内容:
                   android:scheme 用于指定数据的协议部分,如http
                   android:host 用于指定数据的主机名, 如www.baidu.com
                   android:port 用于指定数据的端口邠,一般紧随主机名之后
                   android:path
                   android:mineType

         只有<data>标签中指定内容和Intent中携带的Data完全一致时,活动才能响应该Intent
         一般在<data>标签中不会指定过多内容,如上面只指定android:scheme为http,就可以响应所有http协议的Intent:
                          <data android:scheme="http"/>

         除了http协议外还有geo表示地理位置、tel表示拨打电话:
                      intent.setData(Uri.parse("tel:10086"));


  4、向下一个活动传递数据

        Intent提供 putExtar()方法的重载,可以把数据暂存在Intent中
        intent.putExtra("extra_data", data):
            第一个参数是键,第二个参数是真正要传递的数据
       
        public void onClick(View v) {
                   String data = "xxxx";
                   Intent intent = new Intent(FirstActivit.this, SecondActivity.class);
                   intent.putExtra("extra_data", data);
                   startActivity(intent);
        }


        取出数据:
                 protected void onCreate(Bundle savedInstanceState) {
                          super.onCreate(savedInstanceState);
                          setContentView(R.layout.second_layout);
                          Intent intent = getIntent();
                          String data = intent.getStringExtra("extra_data");
                  }
        getIntent()方法获取Intent对象
        getXxxExtra()传入参数为键,获得相应的数据,具体有getIntExtra()、getBooleanExtra()等


   5、返回数据给上一个活动

         主要通过startActivityForResult()启动活动,通过setResult()设置返回的请求码与Intent,通过onActivityResult()获得返回的数据


        a、Activity中有一个startActivityForResult()方法也可以启动活动,这个方法    期望  在  活动销毁  的时候能返回一个结果给上一个活动
             startActivitForResult(intent, 1)方法的参数:第一个参数是Intent,第二个参数是请求码requestCode,用于判断数据来源

        b、SecondActivity中onClick()://Ps:这是通过按钮回到启动活动,所以覆写按钮监听方法
                 public void onClick(View v) {
                      Intent intent = new Intent();
                      intent.putExtra("data_return", "Hello FirstActivity");
                      setResult(RESULT_OK, intent);
                      finish();
                }
            setResult()方法专门用于向上一个活动返回数据,接收两个参数:
                                第一个用于返回处理结果resultCode,一般是RESULT_OK或RESULT_CANCELED
                                第二个把带有数据的Intent对象传递回去
        
        c、使用startActivityForResult()启动活动时,在活动被销毁后会回调上一个活动的onActivityResult()方法,所以需要在第一个活动中覆写这个方法来得到数据
             
             @Override
             protected void onActivityResult(int requestCode, inte resultCode, Intent data) {
                         switch (reqeustCode) {
                                case 1:
                                           if (resultCode == RESULT_OK) {
                                                   String returnedData = data.getStringExtar("data_return");
                                           }
                                           break;
                               default:
                         }
             }
             Ps:关于break的问题:break可用可不用,没有break时顺序执行,直到遇到break跳出或者执行到末尾
            
           onActivityResult()三个参数:
                    第一个参数requestCode,即我们在启动活动中传入的请求码
                    第二个参数resultCode,即我们在返回数据时传入的处理结果
                   第三个参数,即携带返回数据的Intent对象

                   requestCode判断数据来源,resultCode判断处理结果是否成功


          如果用户是通过Back键回到启动活动,可以通过覆写onBackPressed()方法来解决问题


4、活动的生命周期

        1、返回栈

                Android中的活动是可以层叠的,每启动一个新的活动,就会覆盖在原来的活动智商,点击Back会销毁最上面的活动,下面的活动就会重新显示出来
               

Android使用任务(Task)来管理活动,一个任务就是一组存放在栈里的活动的集合,这个栈也被称作返回栈(Back Stack)

        默认情况下,每当我们启动一个新的活动,它会在返回栈中入栈,并处于栈顶的位置。每当我们按下Back或者调用finish()方法销毁一个方法时,处于栈顶的活动就会出栈,前一个活动就会重新处于栈顶,系统总是会显示处于栈顶的活动给用户。

        返回栈管理活动入栈出栈操作:

              

  2、活动状态

     每个活动在其生命周期中最多可能会有4种状态

     运行状态:

         当活动位于栈顶时,活动就处于运行状态。

         系统最不愿意回收运行状态的活动

     暂停状态:

         当一个活动不再位于栈顶,但仍然可见时,活动就处于暂停状态。

         仍然可见是指:并不是所有的活动都占满整个屏幕,比如对话框形式的活动,它只占用屏幕中间一部分。

        暂停状态活动仍然是完全存活着的,系统次不愿意回收

     停止状态:

        当一个活动不再处于栈顶,并且完全不可见的时候,活动处于停止状态。

        系统仍然为该活动保存相应的状态和成员变量。

        系统第三不愿意回收

     销毁状态:

         活动从返回栈中移除后,活动就变成销毁状态。

         系统最倾向于回收销毁状态的活动

  3、活动的生存期

     Activity类有7个回调方法,覆盖了活动生命周期的每一个环节。

     7个回调方法:

         onCreate():

             活动第一次被创建时调用

             完成活动的初始化操作

         onStart():

             活动由不可见变为可见时调用

         onResume():

             活动准备好和用户交互时调用

             活动一定是位于栈顶的,并处于运行状态

         onPause():

             系统准备去启动或者恢复另一个活动的时候调用

             释放小号的CPU资源,保存一些关键数据

             执行速度要快,不能影响新的栈顶活动

         onStop():

              活动完全不可见的时候调用

              onPasue()的区别在于,新启动的活动如果是对话框形式的话,onPause()会被调用,而onStop()不会被执行

         onDestroy():

               活动被销毁前调用,之后活动的状态变为销毁状态

         onRestart():

               活动由停止状态变为运行状态时调用

     三种生存期:

         完整生存期:

             onCreate()onDestroy()方法之间所经历的。onCreate()完成初始化,onDestroy()完成内存释放

         可见生存期:

             onStart()onStop()方法之间所经历的。

             在此期间,活动对于用户总是可见的

             onStart()中对资源进行加载,onStop()中对资源进行释放

         前台生存期:

             onResume()onPause()方法之间所经历的。

             此时,活动总是处于运行状态,可以和用户进行交互

     活动生命周期示意图:

               

  3、体验活动的生命周期

      android:theme=”@style/Theme.AppCompat.Dialog”:

          android:theme属性,是用于给当前活动指定主题的,Android系统内置很多主题

  4、活动被回收的解决办法

     Activity提供了一个onSaveInstanceState()回调方法

     这个方法可以保证在活动被回收之前一定会被调用

     onSaveInstanceState()方法中保存数据:

         该方法提供一个Bundle类型参数

         Bundle提供一系列方法保存数据,比如:

putString()保存字符串

putInt()保存整数

          每个保存方法传入两个参数:

              一个参数是键

              一个是保存的值

     代码如下:

         @Override

               Protected void onSaveInstanceState(Bundle outState) {

                  Super.onSaveInstanceState(outState);

                  String tempData = “Something you just typed”;

                  outState.putString(“data_key”, tempData);

               }

       onCreate()方法也有一个Bundle类型参数,一般为null,但如果onSaveInstanceStae()方法被调用过,则该Bundle参数就会带有之前保存的全部数据

       BundleIntent保存和取出数据的方法对比:

             Bundle保存:bundle.put类型名(键名”,)

             Intent保存:intent.putExtra(键名”,)

             Bundle取出:bundle.get类型名(键名”)

             Intent取出:intent.get类型名(键名”)

       Intent还可以和Bundle结合使用:

             使用Bundle保存数据,再用Intent保存Bundle

5、活动的启动模式

四种启动模式:

    standard

    singleTop

    singleTask

    singleInstance

AndroidManifest.xml中通过<activity>标签指定android:launcherMode属性来选择启动模式

1、Standard

       默认启动模式

       每次启动都会创建该活动的一个新的实例

       示意图:

 

              

     2、singleTop

        android:launchMode=”singleTop”

启动活动时,如果发现返回栈的栈顶已经是该活动,则直接使用它,不会再创建新的活动实例

如果活动不是在栈顶,则会再创建新的活动实例

示意图:

               

     3、singleTask

        每次启动该活动时系统首先检查返回栈中是否存在该活动的实例,如果发现已经存在则直接使用该实例,并把这个活动智商的所有活动统统出栈,如果没有发现则重新创建一个实例

        保证每次只有一个实例

        示意图:

               

     4、singleInstance

        活动会启用一个新的返回栈来管理这个活动

        使不同的程序共享一个活动实例成为可能

        示意图:

               

  6、活动的最佳实践

      技巧也很重要

      1、知晓当前在哪一个活动

          AppCompatActivity和具体Activity之间加一个普通java类,使其打印当前实例类名

           实现如下:

               创建BaseActivity继承AppCompatActivity

               修改具体Activity的继承结构,不再继承自AppCompatActivity,改为继承自BaseActivity

               覆写BaseActivityonCreate()方法:

                   加入一行Log.d(“BaseActivity”, getClass().getSimpleName());

      2、随时随地退出程序

         新建一个ActivityCollector类作为活动管理类

         通过静态List管理活动,有三个方法:静态添加活动类、静态删除活动类、静态销毁所有活动类

         BaseActivityonCreate()方法中使用ActivitCollector.add(this);

         BaseActivityonDestroy()方法中使用ActivitCollector.remove(this);

         在任何想直接退出的地方加一个按钮,在按钮的OnClick方法中加入:

             ActivityCollector.finishAll();

         Ps:android.os.Process.killProcess(android.os.Process.myPid());杀死当前进程,该方法只能杀死当前进程,不能杀掉其他进程

      3、启动活动的最佳写法

         在要被启动的活动中加入一个方法:

                public static void actionStart(Context context, String data1,String data 2) {

                              Intent intent = new Intent(context, SecondActivity.class);

                              intent.putExtra(“param1”, data1);

                              intent.putExtra(“param2”,data2);

                              context.startActivity(intent);

                          }

                         需要多少启动参数,就加入多少启动参数,然后在启动活动中直接一行启动就行

                         SecondActivity.actionStart(FirstActivity.this, “data1”, “data2”);

               这个方法可以作为代码编写规范使用




原创粉丝点击