45fan.com - 路饭网

搜索: 您的位置主页 > 手机频道 > 阅读资讯:Android活动——Activity浅析

Android活动——Activity浅析

2019-04-20 07:36:22 来源:www.45fan.com 【

Those who dare to fail miserably can achieve greatly.
不怕惨败,才能有伟大的成就。–约翰·肯尼迪

1 Activity 概念

参考文献

  • Android指南
  • 参考文献一:第一行代码
  • 参考文献二:菜鸟教程

  • 活动是一种可以包含用户界面的组件,主要用于和用户进行交互

    活动提供应用程序绘制其UI的窗口。此窗口通常填充屏幕,但可能小于屏幕并浮动在其他窗口的顶部。通常,一个活动在应用程序中实现一个屏幕。例如,应用程序的某个活动可能会实现*“首选项”*屏幕,而另一个活动会实现“ *选择照片”*屏幕。

    大多数应用程序包含多个屏幕,这意味着它们包含多个活动 通常,应用程序中的一个活动被指定为主要活动,这是用户启动应用程序时显示的第一个屏幕。然后,每个活动可以启动另一个活动以执行不同的操作。

    Android活动——Activity浅析

    2 Activity基本用法

  • 所有的活动都要在AndroidManifest.xml中进行注册才能生效。活动的注册声明要放在<application>标签内,在<activity>标签中是晕了android:name来指定具体注册哪一个活动。

  • **配置主活动的方法**就是在<application>标签内加入<intent-filter>标签,并在这个标签内添加

    <action android:name="android.intent.action.MAIN" />
    
    <category android:name="android.intent.category.LAUNCHER" />
    
  • 声明权限

    You can use the manifest’s <activity> tag to control which apps can start a particular activity. A parent activity cannot launch a child activity unless both activities have the same permissions in their manifest. If you declare a<uses-permission> element for a particular activity, the calling activity must have a matching <uses-permission> element.

    <manifest>
    <activity android:name="...."
     android:permission=”com.google.socialapp.permission.SHARE_POST”
    />
    

    如果要允许调用SocialApp,您的应用必须与SocialApp清单中设置的权限相匹配

    <manifest> <uses-permission android:name = “com.google.socialapp.permission.SHARE_POST” /> </ manifest>
    

    销毁一个活动

    销毁活动只要按back键就可以,而且Activity类提供一个finish()方法,活动中调用这个方法就可以销毁当前活动。将前述的按钮监听器代码加入该方法即可。

    使用Intent

    使用显式Intent

    Intent事Android程序中各组件之间进行交互的一种重要方式,不仅可以指明当前组件想要执行的动作,还可以在不同组件之间进行传递数据。被用于启动活动,启动服务以及发送广播等场景

    Activity类中提供一个startActivity()方法,专门用于启动活动,接受一个Intent参数,构建好的Intent传入该方法就可以启动目标活动了。创建一个新的Activity——SecondActivity。

  • 修改FirstActivity中按钮点击事件代码:
  • public void onClick(View v) {
            Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
            startActivity(intent);
          }
    
  • 或通过IntentComponentName来启动
  • ComponentName cn = new ComponentName("com.vivo.a11085273.activitytest","com.vivo.a11085273.activitytest.ThirdActivity");
    Intent intent = new Intent();
    intent.setComponent(cn);
    startActivity(intent);
    
  • 或通过初始化Intent时指定包名
  • Intent intent = new Intent("android.intent.action.MAIN");
    intent.setClassName("com.vivo.a11085273.activitytest", "com.vivo.a11085273.activitytest.ThirdActivity");
    startActivity(intent);
    

    使用隐式Intent

    不明确指出我们想要启动哪一个活动,指定了一系列更为抽象的action和category等信息,交由系统分析这个Intent,找出合适的Intent去启动。通过Intent的Intent-filter实现。

    <activity android:name=".SecondActivity">
          <intent-filter>
            <action android:name="com.vivo.a11085273.activitytest.ACTION_START" />
            <category android:name="android.intent.category.DEFAULT" />
          </intent-filter>
        </activity>
    

    修改FirstActivity中按钮点击事件:

    @Override
          public void onClick(View v) {
            Intent intent = new Intent("com.vivo.a11085273.activitytest.ACTION_START");
            intent.addCategory("com.vivo.a11085273.activitytest.MY_CATEGORY");
            startActivity(intent);
          }
    

    每个Intent只能指定一个action,但是却能指定多个category。可以调用Intent中的addCategory()方法来添加category。

    隐式Intent其他功能

    使用隐式Intent不仅可以启动程序内的活动,还可以启动其他程序的活动,使得Android多个应用程序之间的功能共享成为了可能。

    示例:

    @Override
          public void onClick(View v) {
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setData(Uri.parse("http://www.google.com.hk"));
            startActivity(intent);
          }
    

    Uri.parse将一个网址字符串解析成一个Uri对象。

    如果自己创建一个活动,也可以响应打开网页的Intent。

    新建Activity,编辑布局文件,在AndroidManifest.xml中修改ThirdActivity注册信息:

    <activity android:name=".ThirdActivity">
          <intent-filter tools:ignore="AppLinkUrlError">
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:scheme="http" />
          </intent-filter>
        </activity>
    

    除了http协议外,可以指定很多其他协议,比如:geo表示显示地理位置,tel表示拨打电话。

    3 Activity间数据传递

    一个app一般都是由多个Activity构成,这就涉及到多个Acitivity间数据传递。

    Android活动——Activity浅析

    Intent向下一个活动传递数据

    Intent中提供了一些列putExtra()方法的重载,可以吧想要传递的数据暂存在Intent中,启动了另一个活动后,把这些数据从Intent中取出来就可以。

    示例:在FirstActivity中修改点击按钮监听代码

    @Override
          public void onClick(View v) {
            String data = "Hello SecondActivity";
            Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
            intent.putExtra("extra_data", data);
            startActivity(intent);
          }
    

    修改SecondActivity中代码:

    @Override
      protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.second_activity);
        Intent intent = getIntent();
        String data = intent.getStringExtra("extra_data");
        Log.d("SecondActivity", data);
      }
    

    返回数据给上一个活动

    Activity中还有一个startActivityForResult()方法也适用于启动活动,但是该方法期望活动销毁的时候返回一个结果给上一个活动。

    Android活动——Activity浅析

    该方法接收两个参数,一个是Intent,第二个参数是请求码,用于之后在回调中判断数据的来源。

    首先修改FirstActivity中点击按钮监听事件代码:

     @Override
          public void onClick(View v) {
            Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
            startActivityForResult(intent,1);
          }
    

    其次修改SecondActivity中代码:

    @Override
      protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.second_activity);
        Button button2 = (Button) findViewById(R.id.button_2);
        button2.setOnClickListener(new View.OnClickListener() {
    
          @Override
          public void onClick(View v) {
            Intent intent = new Intent();
            intent.putExtra("data_return","Hello FirstActivity");
            setResult(RRSULT_OK, intent);
            finish();
          }
        });
      }
    

    最后在FirstActivity中重写这个方法来得到返回数据:

     @Override
      protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        switch(requestCode) {
          case 1:
            if (resultCode == RESULT_OK) {
              String returnedData = data.getStringExtra("data_return");
              Log.d("FritstActivity",returnedData);
            }
            break;
          default:
        }
      }
    

    如果是通过back键返回,则可以通过在SecondActivity中重写onBackPressed()来解决:

     @Override
      public void onBackPressed() {
        Intent intent = new Intent();
        intent.putExtra("data_return","Hello FirstActivity");
        setResult(RESULT_OK, intent);
        finish();
      }
    

    3 活动的生命周期

    返回栈

    Android中的活动是可以层叠的。每启动一个新的活动,就会覆盖原来的活动之上,点击Back键就会销毁最上面的活动。

    Android是使用任务(Task)来管理活动的,一个任务就是一组存放在栈里的活动的集合,这个栈也称作返回栈(Back Stack)。系统总是会显示处于栈顶活动给用户。

    Android活动——Activity浅析

    活动状态

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

  • 运行状态:

    活动位于返回栈的栈顶时,这时活动就处于运行状态。

  • 暂停状态:

    活动不处于栈顶时,但是仍然可见,活动就进入暂停状态。

  • 停止状态:

    活动不处于栈顶位置,且完全不可见,就进入停止状态。处于停止状态的活动有可能会被系统回收

  • 销毁状态:

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

  • 活动的生命周期

    Activity类中定义了7种回调方法,覆盖了活动生命周期的每一个环节:

  • onCreate():完成活动的初始化操作,比如加载布局,绑定事件
  • onStart():在活动由不可见变为可见的时候调用
  • onResume():在活动准备好和用户进行交互时调用。该活动一定处于返回栈栈顶,且处于运行状态
  • onPause():系统准备去启动或者恢复另一个活动的时候调用。该方法的执行速度一定要快,否则会影响到新的栈顶活动的使用
  • onStop:在活动完全不可见时调用,与前者的区别时启动的新活动是一个对话框式的活动,那么onPause()方法会得到执行,而该方法不会
  • onDestrory():在活动被销毁之前调用,之后活动变为销毁状态
  • onRestart():由停止状态变为运行时状态之前调用,活动被重新启动。
  • 除了**onRestart()**方法之外,其他都是两两相对的,活动分为3中生存期:

  • 完整生存期:活动在onCreate()onDestrory()之间经历的就是完整生存期
  • 可见生存期:活动在onStart()onStop之间经历的就是可见生存期。活动对于用户总是可见的,即便有可能无法和用户进行交互。
  • 前台生存期:活动在onResume()onPause()之间经历的就是前台生存期。活动总是处于运行状态,此时活动可以和用户进行交互。
  • Android活动——Activity浅析

    onCreate()代码示例:

    TextView mTextView;
    
    // some transient state for the activity instance
    String mGameState;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
      // call the super class onCreate to complete the creation of activity like
      // the view hierarchy
      super.onCreate(savedInstanceState);
    
      // recovering the instance state
      if (savedInstanceState != null) {
        mGameState = savedInstanceState.getString(GAME_STATE_KEY);
      }
    
      // set the user interface layout for this activity
      // the layout file is defined in the project res/layout/main_activity.xml file
      setContentView(R.layout.main_activity);
    
      // initialize member TextView so we can manipulate it later
      mTextView = (TextView) findViewById(R.id.text_view);
    }
    
    // This callback is called only when there is a saved instance that is previously saved by using
    // onSaveInstanceState(). We restore some state in onCreate(), while we can optionally restore
    // other state here, possibly usable after onStart() has completed.
    // The savedInstanceState Bundle is same as the one used in onCreate().
    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) {
      mTextView.setText(savedInstanceState.getString(TEXT_VIEW_KEY));
    }
    
    // invoked when the activity may be temporarily destroyed, save the instance state here
    @Override
    public void onSaveInstanceState(Bundle outState) {
      outState.putString(GAME_STATE_KEY, mGameState);
      outState.putString(TEXT_VIEW_KEY, mTextView.getText());
    
      // call superclass to save any view hierarchy
      super.onSaveInstanceState(outState);
    }
    

    活动被回收

    如果一个活动进入停止状态,有可能被系统回收,其中的数据在回收时可能得不到保存。

    Activity中提供了一个onSaveInstanceState()回调方法,这个方法可以保证活动被回收之前一定被调用,可以通过这个方法来保存数据。

    @Override
      protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        String tempData = "Something you just typed";
        outState.putString("data_key", tempData);
      }
    

    数据的取值可以在onCreate()方法中取出:

     if (savedInstanceState != null) {
          String tempData = savedInstanceState.getString("data_key");
          Log.d(TAG, tempData);
        }
    

    4 横竖屏切换与状态保存

    官方文档:横竖屏切换

    参考文献一:gdutxiaoxu博客

    参考文献二:菜鸟教程

    参考文献三:横竖屏知识小结


    App横竖屏切换的时候会销毁当前的Activity然后重新创建一个,你可以自行在生命周期 的每个方法里都添加打印Log的语句,来进行判断,又或者设一个按钮一个TextView点击按钮后,修改TextView 文本,然后横竖屏切换,会神奇的发现TextView文本变回之前的内容了! 横竖屏切换时Activity走下述生命周期:
    onPause-> onStop-> onDestory-> onCreate->onStart->onResume

    禁止屏幕横竖屏自动切换

    如果要禁止屏幕横竖屏自动切换,在AndroidManifest.xml中为Activity添加一个属性:android:screenOrientaiton

    。。。

    5 启动模式

    启动模式一共有4种,分别是:standardsingleTopsingleTasksingleInstance。可以再AndroidManifest.xml中通过<activity>标签指定android:launchMode属性来选择启动模式。

    standard

    默认模式,每当启动一个新活动,就会在返回栈中入栈,并处于栈顶位置。该模式的活动无论这个活动是否在返回栈中存在,每次启动都会创建该活动的新实例。

    Android活动——Activity浅析

    singleTop

    当活动指定为singleTop模式,启动活动时如果发现返回栈的栈顶已经是该活动,则认为可以直接使用它,不会再创建新的活动实例。

    Android活动——Activity浅析

    singleTask

    当活动的启动模式指定为singleTask,每次启动该活动系统首先会在返回栈中检查是否存在该活动的实例,如果发现就直接使用,并把这个活动之上的所有活动统统出栈。如果没有发现就创建一个新的活动实例。

    Android活动——Activity浅析

    singleInstance

    指定为singleInstance模式的活动会启用一个新的返回栈来管理这个活动(如果singleTask模式指定了不同的taskAffinity,也会启动一个新的返回栈)。这种模式解决了其他程序和我们的程序共享一个活动的实例。

    Android活动——Activity浅析

    6 活动实践

    确定当前活动

    例如需要在某个界面上修改相关东西,快速定位该界面对应的活动

    新建一个Java类:BaseActivity,继承AppCompatActivity,重写onCreate()方法。

    @Override
      protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("BaseActivity", getClass().getSimpleName());
      }
    

    oncreate()方法中获取了当前实例的类名,然后将项目中所有活动的父类都不再继承AppCompatActivity,而是继承BaseActivity,这样查看日志,,每当进入一个活动的界面,该活动的类名就被打印出来。

    随时退出程序

    按home键只是将程序挂起,并没有退出程序,如果程序需要一个注销或者退出的功能,只需要一个专门的集合类对所有的活动进行管理就可以。

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

    public class ActivityCollector {
    
      public static List<Activity> activities = new ArrayList<>();
    
      public static void addActivity(Activity activity) {
        activities.add(activity);
      }
    
      public static void removeActivity(Activity activity) {
        activities.remove(activity);
      }
    
      public static void finishAll() {
        for (Activity activity : activities) {
          if (!activity.isFinishing()) {
            activity.finish();
          }
        }
      }
    }
    

    之后修改BaseActivity:

    public class BaseActivity extends AppCompatActivity {
    
      @Override
      protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("BaseActivity", getClass().getSimpleName());
        ActivityCollector.addActivity(this);
      }
    
      @Override
      protected void onDestroy() {
        super.onDestroy();
        ActivityCollector.removeActivity(this);
      }
    }
    

    如果需要在某个地方退出程序,调用ActivityCollector.finishAll()方法就可以。

    可以再销毁所有活动代码的后面加上杀掉当前进程,确保程序完全退出:

    android.os.Process.killProcess(android.os.Process.myPid());
    

    其中killProcess()方法用于杀掉一个进程,接收一个进程参数,通过myPid()方法可以获得当前程序的进程id。

    启动活动最佳写法

    如果你的模块需要将一些重要数据传递给另一个模块,例如两个字符串参数,但是你不清楚启动这个活动需要传递哪些数据,只需在启动活动添加一个actionStart()方法。

    public static void actionStart(Context context, String data1, String data2) {
        Intent intent = new Intent(context, SecondActivity.class);
        intent.putExtra("param1", data1);
        intent.putExtra("param2", data2);
        context.startActivities(intent);
      }
    

    这时候如果想要启动该活动,只需一行代码就可以启动SecondActivity。

     button1.setOnClickListener(new View.OnClickListener() {
    
          @Override
          public void onClick(View v) {
          SecondActivity.actionStart(FirstActivity.this, "data1", "data2");
          }
     }
    

    7 系统提供常见Activity

    //1.拨打电话
    // 给移动客服10086拨打电话
    Uri uri = Uri.parse("tel:10086");
    Intent intent = new Intent(Intent.ACTION_DIAL, uri);
    startActivity(intent);
    
    //2.发送短信
    // 给10086发送内容为“Hello”的短信
    Uri uri = Uri.parse("smsto:10086");
    Intent intent = new Intent(Intent.ACTION_SENDTO, uri);
    intent.putExtra("sms_body", "Hello");
    startActivity(intent);
    
    //3.发送彩信(相当于发送带附件的短信)
    Intent intent = new Intent(Intent.ACTION_SEND);
    intent.putExtra("sms_body", "Hello");
    Uri uri = Uri.parse("content://media/external/images/media/23");
    intent.putExtra(Intent.EXTRA_STREAM, uri);
    intent.setType("image/png");
    startActivity(intent);
    
    //4.打开浏览器:
    // 打开Google主页
    Uri uri = Uri.parse("http://www.baidu.com");
    Intent intent = new Intent(Intent.ACTION_VIEW, uri);
    startActivity(intent);
    
    //5.发送电子邮件:(阉割了Google服务的没戏!!!!)
    // 给someone@domain.com发邮件
    Uri uri = Uri.parse("mailto:someone@domain.com");
    Intent intent = new Intent(Intent.ACTION_SENDTO, uri);
    startActivity(intent);
    // 给someone@domain.com发邮件发送内容为“Hello”的邮件
    Intent intent = new Intent(Intent.ACTION_SEND);
    intent

    本文地址:http://www.45fan.com/a/luyou/100433.html
    Tags: Android 活动 Activity
    编辑:路饭网
  • 上一篇:数据库:mySQL安装
  • 下一篇:没有了
  • 关于我们 | 联系我们 | 友情链接 | 网站地图 | Sitemap | App | 返回顶部