浅谈Android的四大组件

Android的四大组件分别有Activity、Content Provider、Broadcast 、Service

四大组件都有一个特点,就是必须要在AndroidManifest文件在中注册

首先讲一下Activity,我觉得Activity最基本的就是要熟悉他的生命周期。

分别有7个

  • onCreate():每次启动Activity都要调用这个方法
  • onStart():从不可见变为可见都会调用这个方法
  • onResume():这个方法一定保证了当前Activity就是在栈顶,就是该Activity一定是你看到的画面
  • onPause():这个方法是一个过渡,让你可以保存一些关键数据
  • onStop():调用这个方法代表着当前的Activity变得完全不可见
  • onDestroy():调用这个方法,当前Activity就会被销毁了
  • onRestart():当Activity由停止状态变为活动状态,该方法就会被调用

然后要想成为一个Activity类,必须继承Activity
然后如果要使用Fragment,就要继承FragmentActivity
然后如果要使用AppCompat库,就要继承AppCompatActivity,当然AppCompatActivity就是FragmentActivity的子类,所以也可以用Fragment

谷歌官方给出的图,我觉得一定要把他映射在脑中

浅谈Android的四大组件_第1张图片


Activity的保存数据机制

有时候当你退出掉当前的Activity界面,Android可能会回收了这个activity,然后数据就没有了,这是一种很差的用户体验。

但是Android提供了完美的解决方案

    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        super.onSaveInstanceState(savedInstanceState);
    }

常见的用法是覆盖onSaveInstanceState(Bundle outState),把数据暂存在Bundle中,然后操作系统会将Bundle对象放入activity记录中,当activity被销毁就会调用onSaveInstanceState(Bundle outState)

例如

    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        savedInstanceState.putSerializable(CURRENT_FILTERING_KEY, mTasksPresenter.getFiltering());
        super.onSaveInstanceState(savedInstanceState);
    }

然后在Activity的onCreate()方法中取出数据

        if (savedInstanceState != null) {
            TasksFilterType currentFiltering =
                    (TasksFilterType) savedInstanceState.getSerializable(CURRENT_FILTERING_KEY);
        }





接下来讲一下Content Provider

现在Android处理数据共享都是用Content Provider,其他的已经被废弃了,
所以如果你的应用程序要共享自己的数据还是用别的应用程序共享出来的数据,都应该用Content Provider

首先是用别人共享出来的数据,要借助到ContentResolver,通过Context的getContentResolver获取这个实例,当然要声明权限,这我就不多说了

ContentResolver 方法可提供持续存储的基本“CRUD”(创建、检索、更新和删除)功能。

内容 URI 是用于在提供程序中标识数据的 URI。内容 URI 包括整个提供程序的符号名称(其授权:authority)和一个指向表的名称(路径:path)。


内容URI的标准格式( 字符串 content://(架构)始终显示):

它为表使用的内容 URI 模式是 content://< authority>/< path>
为单个行使用的内容 URI 模式则是 content://< authority>/< path>/< id>

大概不懂什么是authoritypath

authority在创建Content Provider的时候在Android Manifest中声明Provider的时候要指明一个android:authorities的符号,这个就是了。
一般是由包名.provider组成

例如,如果您的 Android 软件包名称为 com.example.< appname>,则应为提供程序提供 com.example.< appname>.provider 授权。

path 用于对同一程序的不同表进行区分


- *:匹配由任意长度的任何有效字符组成的字符串
- #:匹配由任意长度的数字字符组成的字符串

例如:

content://user_dictionary/words
content://example.content.provider/table1

通常将URI字符串解析成Uri对象
通过Uri.parse(String uri);

Uri uri = Uri.parse(“content://example.content.provider/table1”)


然后接下来,运用CRUD的操作就可以了

  • getContentResolver.query(uri , SQL语句);
  • getContentResolver.insert(uri , SQL语句);
  • getContentResolver.update(uri , SQL语句);
  • getContentResolver.delete(uri , SQL语句);


然后讲一下实现Content Provider自定义Provider

首先创建一个类继承ContentProvider,然后实现6个抽象方法

public class MyProvider extends ContentProvider {
    @Override
    public boolean onCreate() {
        return false;
    }

    @Nullable
    @Override
    public Cursor query(Uri uri, String[] strings, String s, String[] strings1, String s1) {
        return null;
    }

    @Nullable
    @Override
    public String getType(Uri uri) {
        return null;
    }

    @Nullable
    @Override
    public Uri insert(Uri uri, ContentValues contentValues) {
        return null;
    }

    @Override
    public int delete(Uri uri, String s, String[] strings) {
        return 0;
    }

    @Override
    public int update(Uri uri, ContentValues contentValues, String s, String[] strings) {
        return 0;
    }
}

具体就自己查询android文档的资料




接下来讲一下Broadcast

broadcast其实与Intent很类似,只不过broadcast intent可以同时被多个叫做broadcast receiver接收

首先Broadcast可以有广播接收器和广播发送:


广播接收器Broadcast receiver

广播接收器broadcast receiver可以是动态注册和静态注册
首先是动态注册,灵活性很好,可以动态控制注册和注销,但是有一个缺点是必须要程序启动才可以
接受广播,这个和静态注册刚刚好相反。

private MyReceiver myReceiver;
@Override
public void onCreate(Bundle savedInstanceState){
    super.onCreate(saveInstanceState);
    setContentView(R.layout.activity_main);
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction("这里是要添加的action");
    //创建并初始化MyReceiver
    myReceiver = new MyReceiver();
    //注册接收器
    registerReceiver(myReceiver , intentFilter);

}

@Override
public void onDestroy(){
    super.onDestroy();
    //记得一定要取消注册才行
    unregisterReceiver(myReceiver);
}


//创建一个广播接收器,继承BroadcastReceiver
class MyReceiver extends BroadcastReceiver{
    //必须实现的方法
    @Override
    public void onReceive(Context context , Intent intent){

    }
}


静态注册,优点就是不需要启动程序就可以接收广播了,比如有的是要监听开机的广播,这时候就要用到静态注册了,并且静态注册必须要在Android Manifest清单文件中注册才可以。

<receiver
    这里要用下面创建的receiver(用全包名)
    android:name=".MyReceiver"
    android:enable="true"
    android:exported="true"
    <intent-filter>
        <action android:name="这里添加action"/>
    intent-filter>
receiver>
//这里只要继承BroadcastReceiver创建一个MyReceiver就好了
public class MyReceiver extends BroadcastReceiver{
    @Override
    public void onReceive(Context context , Intent intent){
        //如果是有序广播可以通过调用abortBroadcast()截断广播
        abortBroadcast();
    }
}


发送广播

然后发送的broadcast广播分为两种:一种是标准广播(同时性的),一种是有序广播(有先后顺序的)
标准广播主要是通过Context的sendBroadcast(Intent intent)

Intent intent = new Intent("这里填写receiver的action");
sendBroadcast(intent);

而有序广播主要是通过Context的sendOrderedBroadcast(Intent intent , String receiverPermission)

Intent intent = new Intent("这里填写receiver的action");
sendBroadcast(intent , null);

在receiver上也要设置一下优先级,通过android:priority=”“,级别越高,越先接收到,并且可以通过abortBroadcast()来截断广播,截断后后面的就无法接收这条广播了

<receiver
    这里要用下面创建的receiver(用全包名)
    android:name=".MyReceiver"
    android:enable="true"
    android:exported="true"
    <intent-filter android:priority="100">
        <action android:name="这里添加action"/>
    intent-filter>
receiver>


本地广播

当然很多时候我们只需要本地广播就可以了,并且它比较安全,这个广播的传递只可以在应用程序内传递,保证了其他的应用无法接收到

本地广播接收器只可以动态注册,不能静态注册的

发送广播与接收广播

//发送本地广播
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(Context context);
localBroadcastManager.sendBroadcast(Intent intent);
private MyReceiver myReceiver;
private LocalBroadcastManager localBroadcastManager;
@Override
public void onCreate(Bundle savedInstanceState){
    super.onCreate(saveInstanceState);
    setContentView(R.layout.activity_main);
    //初始化localBroadcastManager
    localBroadcastManager = LocalBroadcastManager.getInstance(this);
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction("这里是要添加的action");
    //创建并初始化MyReceiver
    myReceiver = new MyReceiver();
    //注册本地接收器
    localBroadcastManager.registerReceiver(myReceiver , intentFilter);

}

@Override
public void onDestroy(){
    super.onDestroy();
    //记得一定要取消注册才行
    localBroadcastManager.unregisterReceiver(myReceiver);
}


//创建一个广播接收器,继承BroadcastReceiver
class MyReceiver extends BroadcastReceiver{
    //必须实现的方法
    @Override
    public void onReceive(Context context , Intent intent){

    }
}

相信大家都发现,本地广播在用法上和普通的广播基本是一样的,只是在有的地方前面加一个localBroadcastManager而已。

但是需要注意的是,在onReceive()中不要添加过多的逻辑或者耗时操作,会报错的,因为在onReceive()方法是不允许开启线程的。





接下来讲一下Service

先看一下Service的生命周期:
浅谈Android的四大组件_第2张图片
其中如果你要实现一个Service一定要实现里面的抽象方法onBind(),



然后有几个比较重点的方法

onCreate():只有在第一次创建Service的时候会调用,如果已经存在了是不会再调用了

onStartCommand():每次启动Service的时候都会调用,不管存不存在,另外如果调用了这个方法就会在后台无限期的运行,可通过stopService()或者stopSelf()停止

onBind():当另一个组件想通过调用 bindService() 与服务绑定时,系统将调用此方法。在此方法的实现中,您必须通过返回 IBinder 提供一个接口,供客户端用来与服务进行通信。请务必实现此方法,但如果您并不希望允许绑定,则应返回 null。

onDestroy():当服务不再使用且将被销毁时,系统将调用此方法。服务应该实现此方法来清理所有资源,如线程、注册的侦听器、接收器等。 这是服务接收的最后一个调用。


startService()启动服务

一般从一个组件调用startService(intent service);启动Service,如果Service是不存在的,就先调用onCreate();方法,然后调用onStartCommand();此后Service会一直运行,就算Activity被销毁了。接着调用stopService或者stopSelf()方法停止Service,onDestroy就会被调用。

bindService()启动服务

然而,如果调用bindService(),是不会调用onStartCommand()的,然后Android 系统随后调用服务的 onBind() 方法,该方法返回用于与服务交互的 IBinder,绑定是异步的。bindService() 会立即返回,“不会”使 IBinder 返回客户端。而通过客户端(Activity等)必须创建一个 ServiceConnection 实例,并将其传递给 bindService()。ServiceConnection 包括一个回调方法,系统通过调用它来传递 IBinder。当最后一个客户端取消与服务的绑定时,系统会将服务销毁(除非 startService() 也启动了该服务)。

另外需要注意的是bindService()启动服务,只要Activity被销毁了,Service也同样跟着销毁的


服务端的实现

public class LocalService extends Service {
    // Binder given to clients
    private final IBinder mBinder = new LocalBinder();
    // Random number generator
    private final Random mGenerator = new Random();


    public class LocalBinder extends Binder {
        LocalService getService() {
            // Return this instance of LocalService so clients can call public methods
            return LocalService.this;
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    /** method for clients */
    public int getRandomNumber() {
      return mGenerator.nextInt(100);
    }
}



客户端的实现

public class BindingActivity extends Activity {
    LocalService mService;
    boolean mBound = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

    @Override
    protected void onStart() {
        super.onStart();
        // Bind to LocalService
        Intent intent = new Intent(this, LocalService.class);
        //这里需要传入一个ServiceConnnection参数用作回调
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }


    @Override
    protected void onStop() {
        super.onStop();
        // Unbind from the service
        if (mBound) {
            unbindService(mConnection);
            mBound = false;
        }
    }



    public void onButtonClick(View v) {
        if (mBound) {

            int num = mService.getRandomNumber();
            Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
        }
    }

   /*
       连接成功就会调用onServiceConnected(ComponentName className,
                IBinder service),
       连接失败就会调用onServiceDisconnected(ComponentName arg0)
   */
    private ServiceConnection mConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName className,
                IBinder service) {
            // We've bound to LocalService, cast the IBinder and get LocalService instance
            LocalBinder binder = (LocalBinder) service;
            mService = binder.getService();
            mBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            mBound = false;
        }
    };
}

应用组件(如 Activity)可以通过调用 startService() 方法并传递 Intent 对象(指定服务并包含待使用服务的所有数据)来启动服务。服务通过 onStartCommand() 方法接收此 Intent。

浅谈Android的四大组件_第3张图片

接下来的前台服务和IntentService这部分在这里就不细讲了’


你可能感兴趣的:(Android)