Activity & Broadcast

Activity

Activity是一个Android的应用组件,它提供屏幕进行交互。每个Activity都会获得一个用于绘制其用户界面的窗口,窗口可以充满屏幕,也可以小于屏幕并浮动在其他窗口之上。 一个应用通常是由多个彼此松散联系的Activity组成,一般会指定应用中的某个Activity为主活动,也就是说首次启动应用时给用户呈现的Activity。将Activity设为主活动的方法,如下面代码所示需要在AndroidManifest文件中添加以下内容:

 <application>
      ....
     <activity android:name=".MainActivity">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
      </activity>
      ....
 </application>    

Activity的四个状态

1.处于前台的Activity是可见的,并且可以跟用户交互; 2.处于暂停状态,可见,但不能被操作 ;3.停止状态,不可见,不能被操作; 4.销毁状态,activity被系统杀死或者调用finish主动退出。

方法说明是否能事后终止?后接
onCreate()首次创建 Activity 时调用。您应该在此方法中执行所有正常的静态设置 — 创建视图、将数据绑定到列表等等。始终后接onStart()onStart()
onStart()此方法被回调时表示Activity正在启动,此时Activity已处于可见状态,只是还没有在前台显示,因此无法与用户进行交互。可以简单理解为Activity已显示而我们无法看见罢了。onStart()之后如果Activity转入前台,则后接 onResume() 如果 Activity 转入隐藏状态,则后接 onStop()。onResume()或 onStop()
onResume()当此方法回调时,则说明Activity已在前台可见,可与用户交互了(处于前面所说的Active/Running形态),onResume方法与onStart的相同点是两者都表示Activity可见,只不过onStart回调时Activity还是后台无法与用户交互,而onResume则已显示在前台,可与用户交互。始终后接onPause()onPause()
onPause()当前 Activity正在停止(Paused形态),系统即将开始继续另一个Activity时会调用此方法。 它应该非常迅速地执行所需操作,因为它返回后,下一个 Activity 才能继续执行。 如果 Activity 返回前台,则后接 onResume(),如果 Activity 转入对用户不可见状态,则后接 onStop()。onResume()或 onDestroy()
onStop()当前 Activity正在停止(Paused形态),系统即将开始继续另一个Activity时会调用此方法。 它应该非常迅速地执行所需操作,因为它返回后,下一个 Activity 才能继续执行。 如果 Activity 返回前台,则后接 onResume(),如果 Activity 转入对用户不可见状态,则后接 onStop()。onRestart()或 onDestroy()
onDestroy()在 Activity 被销毁前调用。这是 Activity 将收到的最后调用。当 Activity 结束(有人对 Activity 调用了 finish()),或系统为节省空间而暂时销毁该 Activity 实例时,可能会调用它。
onDestroy()在 Activity 已停止并即将再次启动前调用。onStart()

Activity 的整个生命周期发生在 onCreate() 调用与 onDestroy() 调用之间。您的 Activity 应在 onCreate()中执行“全局”状态设置(例如定义布局),并释放 onDestroy()中的所有其余资源。例如,如果您的 Activity 有一个在后台运行的线程,用于从网络上下载数据,它可能会在onCreate() 中创建该线程,然后在onDestroy() 中停止该线程。 Activity 的可见生命周期发生在 onStart() 调用与 onStop() 调用之间。在这段时间,用户可以在屏幕上看到 Activity 并与其交互。例如,当一个新 Activity 启动,并且此 Activity 不再可见时,系统会调用onStop()。您可以在调用这两个方法之间保留向用户显示 Activity 所需的资源。例如,您可以在onStart() 中注册一个 BroadcastReceiver 以监控影响 UI的变化,并在用户无法再看到您显示的内容时在 onStop()中将其取消注册。在 Activity 的整个生命周期,当 Activity 在对用户可见和隐藏两种状态中交替变化时,系统可能会多次调用 onStart() 和 onStop()。 Activity 的前台生命周期发生在 onResume() 调用与 onPause() 调用之间。在这段时间,Activity 位于屏幕上的所有其他 Activity 之前,并具有用户输入焦点。Activity 可频繁转入和转出前台 。 例如,当设备转入休眠状态或出现对话框时,系统会调用 onPause()。由于此状态可能经常发生转变,因此这两个方法中应采用适度轻量级的代码,以避免因转变速度慢而让用户等待。

Activity任务栈

每一个应用对应一个任务栈 activity的实例都保存到任务栈中 启动模式 launchMode standard singleTop 栈顶只有一个实例 singleTask 栈中只有一个实例 singleInstance 整个设备只有一个实例 独占任务栈

屏幕旋转时activity的生命周期 默认先销毁再创建新的activity

android使用栈的结构来保存activity的实例->activity的任务栈 android可以在清单文件中配置launchMode属性来决定activity在栈中创建实例的方式 standard标准模式 默认就是这种模式 只要调用了startActivity就会创建activity对应的实例 singleTop在任务栈的栈顶只有一个实例 如果栈顶存在一个实例 在创建这个activity的对象不会成功 singleTask在任务栈的栈顶只有一个实例 如果在栈中已经不存在了一个singletask的activity 那么再次开启这个activity不会创建一个新的对象 而是把这个activity上面的所有activity都关闭 把这个activity露出来 应用的主界面可以配置成singletask singleinstance在当前设备只有一个实例 并且这个实例会创建一个单独的任务栈 这个栈中只有这一个实例

意图

隐式意图/显式意图 开启Activity 隐式意图 匹配intent-filter 打开其他应用的activity 显式意图 指定路径 指定.class对象 打开自己应用的activity

intent传递数据 A打开B 同时传递数据给B 在B中getIntent()来获取intent 在A Activity中intent.putExtra(key, value)和intent.putExtras() A->B B关闭的时候返回数据给A A 打开B的时候 startActivityForResult(intent, requestCode); 重写onActivityResult(request code, result code, intent data); B Activity 如果有数据传回来 setResult(result code, intent data); finish(); intent可以传递的数据类型:基本数据类型及其数组String Strinf数组 StringArrayListserilazerble parserble(实现了序列化接口的对象及其数组和集合),Interger的ArrayList

案例测试

package com.example.myapplication;
 ​
 import android.content.Intent;
 import android.os.Bundle;
 import android.util.Log;
 import android.view.View;
 import android.widget.Button;
 ​
 import androidx.appcompat.app.AppCompatActivity;
 ​
 public class MainActivity extends AppCompatActivity {
 ​
     private Button button;
 ​
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
         Log.d("Test_Activity", "onCreate show");
         button = (Button)findViewById(R.id.btn1);
         button.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View view) {
                 Intent intent = new Intent(MainActivity.this, SecondActivity.class);
                 startActivity(intent);
             }
         });
     }
 ​
     @Override
     protected void onStart() {
         super.onStart();
         Log.d("Test_Activity","onStart show");
     }
 ​
     @Override
     protected void onResume() {
         super.onResume();
         Log.d("Test_Activity","onResume show");
     }
 ​
     @Override
     protected void onRestart() {
         super.onRestart();
         Log.d("Test_Activity","onRestart show");
     }
 ​
     @Override
     protected void onPause() {
         super.onPause();
         Log.d("Test_Activity","onPause show");
     }
 ​
     @Override
     protected void onStop() {
         super.onStop();
         Log.d("Test_Activity","onStop show");
     }
 ​
     @Override
     protected void onDestroy() {
         super.onDestroy();
         Log.d("Test_Activity","onDestroy show");
     }
 }
package com.example.myapplication;
 ​
 import android.os.Bundle;
 import androidx.activity.EdgeToEdge;
 import androidx.appcompat.app.AppCompatActivity;
 import androidx.core.graphics.Insets;
 import androidx.core.view.ViewCompat;
 import androidx.core.view.WindowInsetsCompat;
 ​
 public class SecondActivity extends AppCompatActivity {
 ​
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_second);
     }
 }

在刚启动程序时

点击Home键回到主界面

重新回到Activity

进入到SecondActivity的界面时

当销毁Activity时

BroadCast

概念

android通过广播来实现不同进程间的通信对应于广播(broadcat)还有一个广播接收器(broadcast receiver)每个广播指定了对应的action 、 type等信息,每个接收器根据这些信息来过滤是否自己要接收的广播。

broadcastreceiver用来接收sendBroadCast方法(发出来的广播) 可以通过intent传递数据 抽象类

广播接收器分为标准广播有序广播

标准广播

标准广播是一种完全异步执行的广播,在广播发出之后,所有的广播接收器几乎都会在同一时刻接收到这条广播的信息,因此他们之间没有任何的先后顺序可言。传播如下图所示。

标准广播中的注册方式分为静态注册动态注册

动态注册

系统频繁发出的广播必须通过动态注册。

动态注册主要是在程序中实现的。首先定义一个广播接收器:

 package com.example.broadcast;
 ​
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.util.Log;
 ​
 public class broadcast_receive extends BroadcastReceiver {
     @Override
     public void onReceive(Context context, Intent intent) {
         Log.i("broadcast", "Receive Information");
     }
 }

定义完广播接收器之后,需要对其进行注册,并设置发送广播信息的方法才能使广播接收器接收信息。

package com.example.broadcast;
 ​
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.os.Bundle;
 import android.util.Log;
 import android.view.View;
 import android.widget.Button;
 ​
 import androidx.appcompat.app.AppCompatActivity;
 ​
 public class BroadCastActivity extends AppCompatActivity {
 ​
     private broadcast_receive receiver;
     private Button button;
 ​
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
 ​
         IntentFilter filter = new IntentFilter();
         filter.addAction("my_broadcast");
         receiver = new broadcast_receive();
         //RECEIVER_EXPORTED 表示外部应用范围,RECEIVER_NOT_EXPORTED 表示非外部应用范围
         registerReceiver(receiver, filter, Context.RECEIVER_EXPORTED);
 ​
         button = findViewById(R.id.btn1);
         button.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View view) {
                 Intent intent = new Intent();
                 intent.setAction("my_broadcast");
                 sendBroadcast(intent);
             }
         });
     }
 ​
     @Override
     protected void onDestroy() {
         super.onDestroy();
         unregisterReceiver(receiver);
     }
 }

静态注册

静态注册我们就不需要在代码中进行注册,只需要在AndroidManifest.xml 中进行一次注册就可以。

 <receiver android:name=".static_broadcast"
             android:exported="true"
             android:enabled="true">
             <intent-filter>
                 <action android:name="MY_Receiver"/>
             </intent-filter>
 </receiver>

发送广播的代码如下所示

package com.example.static_broadcast;
 ​
 import android.content.Intent;
 import android.os.Bundle;
 import android.view.View;
 import android.widget.Button;
 ​
 import androidx.activity.EdgeToEdge;
 import androidx.appcompat.app.AppCompatActivity;
 import androidx.core.graphics.Insets;
 import androidx.core.view.ViewCompat;
 import androidx.core.view.WindowInsetsCompat;
 ​
 public class MainActivity extends AppCompatActivity {
 ​
     private Button button;
 ​
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
 ​
         button = findViewById(R.id.btn);
         button.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View view) {
                 Intent intent=new Intent("MY_Receiver");
                 intent.setPackage(getPackageName());
                 sendBroadcast(intent);
             }
         });
     }
 }

接收函数

package com.example.static_broadcast;
 ​
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.util.Log;
 ​
 public class static_broadcast extends BroadcastReceiver {
     @Override
     public void onReceive(Context context, Intent intent) {
         Log.i("broadcast","receive_message");
     }
 }

试验结果

有序广播

有序广播使得广播接收器有先后顺序,而且前面的广播可以对后续的广播进行截断,以阻止让其继续广播。传播如下图所示,权限高者会先获取得到广播的信息。

权限设置的方式如下

 IntentFilter filter = new IntentFilter();
 filter.addAction("my_broadcast");
 filter.setPriority(200);
 receiver = new broadcast_receive();
 //RECEIVER_EXPORTED 表示外部应用范围,RECEIVER_NOT_EXPORTED 表示非外部应用范围
 registerReceiver(receiver, filter, Context.RECEIVER_NOT_EXPORTED);

调用IntentFilter的setPriority(int priority)方法设置优先级,参数值可以是-1000~1000,值越大,优先级越高。同样的在静态注册中,通过设置intent-filter标签的priority属性来设置优先级,代码如下:

<receiver android:name=".static_broadcast"
             android:exported="true"
             android:enabled="true">
             <intent-filter android:priority="200">
                 <action android:name="MY_Receiver"/>
             </intent-filter>
</receiver>

对后续广播进行截断的方法

public class static_broadcast extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.i("broadcast","receive_message");
        abortBroadcast();
    }
}

为了解决安卓的广播安全问题安卓还引入了 LocalBroadcastManger

发送方

LocalBroadcastManager localManager=LocalBroadcastManager.getInstance(this);
Intent localIntent=new Intent("MY_Receiver");
localManager.sendBroadcast(localIntent);

接收方

IntentFilter localFilter=new IntentFilter("MY_Receiver");
LocalReceiver localReceiver=new LocalReceiver();
localManager.registerReceiver(localReceiver,localFilter);

系统广播

我们可以通过注册来接收到广播发出来的一些系统通知,如飞行模式被打开,音量键被按,等等,下面就是监听系统广播的各个 action

动态注册

IntentFilter filter=new IntentFilter();
filter.addAction("my_broadcast");
receiver=new broadcast_receive();
registerReceiver(receiver,filter, Context.RECEIVER_NOT_EXPORTED);

静态注册

<receiver android:name=".static_broadcast"
     android:exported="true"
     android:enabled="true">
     <intent-filter>
         //以下是对飞行模式做出的广播行为
          <action android:name="android.intent.action.AIRPLANE_MODE"/>
      </intent-filter>
</receiver>

广播内部的原理链接:品茗论道说广播(Broadcast内部机制讲解) - OSCHINA - 中文开源技术交流社区

  • 19
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值