zoukankan      html  css  js  c++  java
  • Activity详解

      Activity是android应用的重要组成单元之一(另外3个是Service,BroadcastReceiver和ContentProvider)。实际应用包含了多个Activity,不同的Activity向用户呈现不同的操作界面。Android应用的多个Activity组成Activity栈,当前活动的Activity位于栈顶。对于Android应用而言,Activity主要负责与用户交互,并向用户呈现应用状态。

    1 建立、配置和使用Activity

    1.1 Activity类简介

    • 当一个Activity定义出来后,该Activity类何时被实例化、它所包含的方法何时被调用,这些都不是由开发者来决定,而是Android系统决定
    • 创建Activity需要重写一个或者多个方法。其中最常见的就是onCreate方法
    •  Activity相关类关系视图

      

    • AccountAuthenticatorActivity:实现账户管理界面的Activity
    • TabActivity实现Tab界面的Activity
    • ListActivity实现列表界面的Activity
    • AliasActivity:别名Activity的基类,启动其他Activity时结束自己
    • ExpandableListActivity实现可扩展列表界面的Activity
    • LauncherActivity:实现Activity列表界面的Activity,当单击列表时,所对应的Activity启动
    • PreferenceActivity:实现程序多参数设置,存储界面的Activity

      对于Activity的具体子类如ListActivity,LauncherActivity,ExpandableActivity等无需实现具体的布局文件,会自动调用默认布局文件。

    示例:PreferenceActivity的使用

    Activity文件

    import android.preference.PreferenceActivity;
    import android.preference.PreferenceFragment;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.widget.Button;
    import android.widget.Toast;
    
    import java.util.List;
    
    public class PreferenceActivityTest extends PreferenceActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
    
            super.onCreate(savedInstanceState);
            if(hasHeaders()){
                Button button = new Button(this);
                button.setText("设置操作");
                setListFooter(button);
            }
        }
    
        public void onBuildHeaders(List<Header> target){
            loadHeadersFromResource(R.xml.preference_headers, target);
        }
    
         public boolean isValidFragment(String fragmentName){
             return   true;//super.isValidFragment(fragmentName);
             //return StockPreferenceFragment.class.getName().equals(fragmentName);
         }
    
        public static class Prefs1Fragment extends PreferenceFragment{
           @Override
            public void onCreate(Bundle savedInstanceState){
               super.onCreate(savedInstanceState);
               addPreferencesFromResource(R.xml.preferences);
           }
        }
    
        public static class Prefs2Fragment extends PreferenceFragment{
            public void onCreate(Bundle savedInstanceState){
                super.onCreate(savedInstanceState);
                addPreferencesFromResource(R.xml.display_prefs);
                String website = getArguments().getString("website");
                Toast.makeText(getActivity(),"网站域名是:" +  website, Toast.LENGTH_SHORT).show();
            }
        }
    }
    View Code

    Preference主页布局文件

    <?xml version="1.0" encoding="utf-8"?>
    <preference-headers
        xmlns:android="http://schemas.android.com/apk/res/android">
        <!-- 指定启动指定PreferenceFragment的列表项 -->
        <header android:fragment=
            "com.example.penghuster.exampletest.PreferenceActivityTest$Prefs1Fragment"
            android:icon="@drawable/ic_settings_applications"
            android:title="程序选项设置"
            android:summary="设置应用的相关选项" />
        <!-- 指定启动指定PreferenceFragment的列表项 -->
        <header android:fragment=
            "com.example.penghuster.exampletest.PreferenceActivityTest$Prefs2Fragment"
            android:icon="@drawable/ic_settings_display"
            android:title="界面选项设置 "
            android:summary="设置显示界面的相关选项">
            <!-- 使用extra可向Activity传入额外的数据 -->
            <extra android:name="website"
                android:value="www.crazyit.org" />
        </header>
        <!-- 使用Intent启动指定Activity的列表项 -->
        <header
            android:icon="@drawable/ic_settings_display"
            android:title="使用Intent"
            android:summary="使用Intent启动某个Activity">
            <intent    android:action="android.intent.action.VIEW"
                android:data="http://www.crazyit.org" />
        </header>
    </preference-headers>
    View Code

    Fragment1布局文件

    <?xml version="1.0" encoding="utf-8"?>
    <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
        <!-- 设置系统铃声 -->
        <RingtonePreference
            android:ringtoneType="all"
            android:title="设置铃声"
            android:summary="选择铃声(测试RingtonePreference)"
            android:showDefault="true"
            android:key="ring_key"
            android:showSilent="true">
        </RingtonePreference>
        <PreferenceCategory android:title="个人信息设置组">
            <!-- 通过输入框填写用户名 -->
            <EditTextPreference
                android:key="name"
                android:title="填写用户名"
                android:summary="填写您的用户名(测试EditTextPreference)"
                android:dialogTitle="您所使用的用户名为:" />
            <!-- 通过列表框选择性别 -->
            <ListPreference
                android:key="gender"
                android:title="性别"
                android:summary="选择您的性别(测试ListPreference)"
                android:dialogTitle="ListPreference"
                android:entries="@array/gender_name_list"
                android:entryValues="@array/gender_value_list" />
        </PreferenceCategory>
        <PreferenceCategory android:title="系统功能设置组 ">
            <CheckBoxPreference
                android:key="autoSave"
                android:title="自动保存进度"
                android:summaryOn="自动保存: 开启"
                android:summaryOff="自动保存: 关闭"
                android:defaultValue="true" />
        </PreferenceCategory>
    </PreferenceScreen>
    View Code

    Fragment2布局文件

    <?xml version="1.0" encoding="utf-8"?>
    <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
        <!-- 设置系统铃声 -->
        <RingtonePreference
            android:ringtoneType="all"
            android:title="设置铃声"
            android:summary="选择铃声(测试RingtonePreference)"
            android:showDefault="true"
            android:key="ring_key"
            android:showSilent="true">
        </RingtonePreference>
        <PreferenceCategory android:title="个人信息设置组">
            <!-- 通过输入框填写用户名 -->
            <EditTextPreference
                android:key="name"
                android:title="填写用户名"
                android:summary="填写您的用户名(测试EditTextPreference)"
                android:dialogTitle="您所使用的用户名为:" />
            <!-- 通过列表框选择性别 -->
            <ListPreference
                android:key="gender"
                android:title="性别"
                android:summary="选择您的性别(测试ListPreference)"
                android:dialogTitle="ListPreference"
                android:entries="@array/gender_name_list"
                android:entryValues="@array/gender_value_list" />
        </PreferenceCategory>
        <PreferenceCategory android:title="系统功能设置组 ">
            <CheckBoxPreference
                android:key="autoSave"
                android:title="自动保存进度"
                android:summaryOn="自动保存: 开启"
                android:summaryOff="自动保存: 关闭"
                android:defaultValue="true" />
        </PreferenceCategory>
    </PreferenceScreen>
    View Code

    注意:需要重写PreferenceActivity的isValidFragment方法

    1.2 配置Activity

    • Android应用要求多有应用程序组件(Activity、Service、ContentProvider、BroadcastReceiver)都必须显式进行配置
    • 只需为<application/>元素添加<Activity />子元素即可,另外需要为Activity元素指定一个或者多个intent-filter,该元素用于指定该Activity可以响应的Intent
    • 从DDMS查看PreferenceActivity输出的配置文件

    1.3 启动关闭Activity

    1.3.1 一个Android应用通常会包含多个Activity,但只有一个Activity会作为程序入口-----但Android应用运行时将会自动启动并执行该Activity。其他Activity一般都由入口Activity启动,或者由入口启动的Activity启动,启动Activity的方法有如下两种:

    • startActivity(Intent intent):启动其他Activity
    • startActivityForResult(Intent intent,int requestCode):以指定的请求码(requestCode)启动Activity,而且程序将会等到新启动Activity的结果(通过重写onActivityResult()方法来获取)

    1.3.2 Activity关闭有两个方法:

    finish(),结束当前Activity

    • finishActivity(int requestCode):结束一startActivityForResult的Activity

    1.4 使用Bundle在Activity之间交换数据

      当一个Activity启动另一个Activity时,常常会有一些数据需要传过去,Activity之间的数据交换是通过Intent来完成,Intent提供了多个重载的方法来携带额外的数据,主要接口如下:

    操作对象 Intent Bundle
    发送

    putExtras( Bundle data)  /  putExtras(String name, Xxx value)

    putXxx(String key, Xxx data)  /  putSerializable(String key, Serializable data)
    接收

    Bundle getextras()         / Xxx getXxxExtras(String name)

    Xxx getXxx(String key)          /   Serializable getSerializable(String key)

    注意:Intent的putExtras方法是智能的,会根据Intent对象内是否存在Bundle对象而自动决定是否需要创建Bundle对象

    总结来说,一个有两种方法进行传输数据:

    • 利用Intent + 内置Bundle 传输数据方法

        发送:Intent intent = new Intent(BundleTest.this,ResultActivity.class);   intent.putExtra("person", (Serializable) p);

        接收:Intent intent = getIntent(); Person p = (Person)intent.getSerializableExtra("person");

    • 利用Intent + 自建Bungle 传输数据方法

        发送:Intent intent = new Intent(BundleTest.this,ResultActivity.class);  Bundle data = new Bundle(); 

                       data.putSerializable("person", p);    intent.putExtras(data);

        接收:Intent intent = getIntent();    Bundle data = intent.getExtras();    Person p = (Person)data.getSerializable("person");

    示例:

     发送Activity代码

    import org.crazyt.model.Person;
    
    import android.app.Activity;
    import android.content.Intent;
    import android.os.Bundle;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.RadioButton;
    
    import java.io.Serializable;
    
    public class BundleTest extends Activity {
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            Button bn = (Button) findViewById(R.id.bn);
            bn.setOnClickListener(new OnClickListener() {
                public void onClick(View v) {
                    EditText name = (EditText) findViewById(R.id.name);
                    EditText passwd = (EditText) findViewById(R.id.passwd);
                    RadioButton male = (RadioButton) findViewById(R.id.male);
                    String gender = male.isChecked() ? "男 " : "女";
                    Person p = new Person(name.getText().toString(), passwd
                            .getText().toString(), gender);
    
                    //创建一个Bundle对象
                    Intent intent = new Intent(BundleTest.this,
                            ResultActivity.class);
    
                    //1、利用Intent + 内置Bundle 传输数据方法
    //                intent.putExtra("person", (Serializable) p);
    
                    //2 、利用Intent + 自建Bungle 传输数据方法
                    Bundle data = new Bundle();
                    data.putSerializable("person", p);
                    intent.putExtras(data);
    
                    //启动intent对应的Activity
                    startActivity(intent);
                }
            });
        }
    }
    View Code

    接收Activity代码

    import org.crazyt.model.Person;
    
    public class ResultActivity extends Activity {
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.result);
    
            TextView name = (TextView) findViewById(R.id.name);
            TextView passwd = (TextView) findViewById(R.id.passwd);
            TextView gender = (TextView) findViewById(R.id.gender);
    
            // 获取启动该Result的Inten
            Intent intent = getIntent();
    
            //直接利用Intent传输数据方法1
    //        Person p = (Person) intent.getSerializableExtra("person");
    
            //直接利用Intent传输数据方法2
            Bundle data = intent.getExtras();
            Person p = (Person) data.getSerializable("person");
    
            name.setText("您的用户名为:" + p.getName());
            passwd.setText("您的密码为:" + p.getPass());
            gender.setText("您的性别为:" + p.getGender());
    
        }
    }
    View Code

    效果图

    点击注册->

    1.5 启动其他Activity并返回结果

      简单地讲,就是当前Activity1启动另一个Activity2,Activity1需要获得Activity2的运行结果;而这也是通过Bundle进行数据交换的,为了获取被启动的Activity所返回的结果,需要从两方面入手:

    • 当前Activity需要重写onActivityResult(int requestCode, int resultCode, Intent intent),当被启动的Activity返回结果时,该方法将会被触发
    • 被启动的Activity需要调用setResult()方法设置处理结果

    示例:

    启动Activity代码

    import android.app.Activity;
    import android.content.Intent;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.TextView;
    
    import org.crazyt.model.Person;
    
    public class ResultActivity extends Activity
    {
        @Override
        public void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.result);
        }
    
        public void click(View view){
            Intent intent = new Intent(ResultActivity.this,
                    BundleTest.class);
            startActivityForResult(intent,0);
        }
    
        public void onActivityResult(int requestCode, int resultCode, Intent intent){
            if (requestCode == resultCode){
                Bundle data  = intent.getExtras();
                Person result = (Person)data.getSerializable("person");
                TextView name = (TextView) findViewById(R.id.name);
                TextView passwd = (TextView) findViewById(R.id.passwd);
                TextView gender = (TextView) findViewById(R.id.gender);
                name.setText("您的用户名为:" + result.getName());
                passwd.setText("您的密码为:" + result.getPass());
                gender.setText("您的性别为:" + result.getGender());
            }
        }
    }
    View Code

    操作Activity代码

    import org.crazyt.model.Person;
    
    import android.app.Activity;
    import android.content.Intent;
    import android.os.Bundle;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.RadioButton;
    
    import java.io.Serializable;
    
    public class BundleTest extends Activity {
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            Button bn = (Button) findViewById(R.id.bn);
            bn.setOnClickListener(new OnClickListener() {
                public void onClick(View v) {
                    EditText name = (EditText) findViewById(R.id.name);
                    EditText passwd = (EditText) findViewById(R.id.passwd);
                    RadioButton male = (RadioButton) findViewById(R.id.male);
                    String gender = male.isChecked() ? "男 " : "女";
                    Person p = new Person(name.getText().toString(), passwd
                            .getText().toString(), gender);
    
                    Intent intent = getIntent();
                    Bundle data = new Bundle();
                    data.putSerializable("person", p);
                    intent.putExtras(data);
                    BundleTest.this.setResult(0, intent);
                    BundleTest.this.finish();
                }
            });
        }
    }
    View Code

    效果图

    -->-->

    2 Acitvity的回调机制

    2.1 定义

      所谓回调,对于一个具有通用性质的程序架构来说,程序架构完成整个应用的通用功能、流程,但在某个特定的点上,需要一段业务相关的代码-----而通用程序架构中无法实现这段代码,那么程序架构会在这个点上留一个空。

    2.2 对于java程序来说,程序架构在某点上留的空,可以以两种方式存在:

    • 以接口的形式存在,该接口由开发者实现,实现该接口时将会实现该接口的方法,那么通用程序架构就会按需回调该方法完成对应业务
    • 以抽象方法(也可以是非抽象方法)的形式存在,这些特定点的方法已经被定义,开发者可以选择性重写这些方法后,通用程序架构就会按需回调该方法完成对应业务

    3 Activity的生命周期

      当Activity处于Android应用中运行时,它的活动状态有android以Activity栈的形式管理,当前活动的Activity位于栈顶。随着不同应用的运行,每个Activity都可能从活动状态转入非活动状态,也可能从非活动状态转入活动状态。

    3.1 Activity生命周期的4个状态

    • 活动状态:当前Activity位于前台,用户可见,可以获取焦点
    • 暂停状态:其他Activity位于前台,该Activity仍然可见(处于全透明或非全屏状态),只是不能获取焦点
    • 停止状态:该Activity不可见,失去焦点
    • 销毁状态:该Activity结束,或Activity所在的dalvik进程被结束

    3.2 activity生命周期示意图

    4 Activity的四种加载模式

    4.1 Task管理方法

    • Android采用Task来管理多个Activity,当启动一个应用时,android就会为之创建一个Task,然后启动这个应用的入口Activity
    • Task是以Activity栈的方式来管理Activity的,先启动的放在Task栈底,后启动的放在Task栈顶。
    • Android没有提供Task的API,Task无法访问,只能调用Activity的getTaskId()方法获取当前Activity所在的Task
    • Activity的加载模式就是负责管理和控制Activity实例化、加载方式、以及与Task之间的加载关系

    4.2 standard:标准模式,这是默认加载模式

      每次通过standard模式来启动Activity时,Android总会为目标Activity创建一个新的Activity实例,并将该实例添加到当前的Task栈中。

    4.3 singleTop:Task顶单例模式

      此模式与standard模式基本类似,唯一不同:当将要被启动的目标Activity已经位于Task栈顶时,系统不会重新创建目标Activity实例,而是直接复用栈顶已有Activity实例

    4.4 singleTask:Task内单例模式

      采用singleTask模式的Activity在同一个Task内只有一个实例,当系统采用singleTask模式启动目标Activity时,分为以下三种情况:

    • 如果启动的目标Activity不存在,系统将会创建目标Activity实例,并置于栈顶
    • 如果启动的目标Activity已经位于Task栈顶,则复用该Activity实例,与singleTop模式相同
    • 如果启动的目前Activity已经存在,但不位于Task栈顶,系统将会把位于该Activity上面的所有Activity实例移出Task栈,从而使得目标Activity转入栈顶

    • 4.5 singleInstance:全局单例模式

      采用singleInstance模式,系统保证无论哪个Task中启动目标Activity,只会创建一个目标Activity实例,并会使用一个全新的Task栈来装载该实例。当系统采用singleInstance模式启动目标Activity时,可以分为以下两种情况:

    • 如果将要启动的目标Activity不存在,系统将会先创建一个全新的Task,在创建目标Activity的实例,并将其加入新的Task的栈顶
    • 如果将要启动的目标Activity已经存在,无论位于哪个应用程序中,无论位于哪个Task中,系统将会把该Activity转到前台,从而使该Activity显示出来
    • 采用该模式加载的Activity总是位于task栈顶,且加载该Activity的Task栈中只有该Activity
  • 相关阅读:
    16. 3Sum Closest
    17. Letter Combinations of a Phone Number
    20. Valid Parentheses
    77. Combinations
    80. Remove Duplicates from Sorted Array II
    82. Remove Duplicates from Sorted List II
    88. Merge Sorted Array
    257. Binary Tree Paths
    225. Implement Stack using Queues
    113. Path Sum II
  • 原文地址:https://www.cnblogs.com/penghuster/p/4892359.html
Copyright © 2011-2022 走看看