Android 四大基础组件
Activity、Service、BroadCast Receiver、Content Provider
•介绍四大组件各自的作用
•探究activity的生命周期以及启动模式
•探究service的生命周期
•探究广播,service通过发送广播与activity通信(广播作为activity里面内部类)
•探究Content Provider

介绍四大组件各自的作用
Activity
Activity是用户操作的可视化界面,它为用户提供了一个完成操作指令的窗口。 需要在Activity创建时调用setContentView()来完成界面的显示,为用户提供交互的入口。
1、通常一个Activity就是一个屏幕
2、Activity之间通过Intent进行通信
3、安卓中每一个Activity都需要在AndroidMainFest.xml文件中声明
Service
Service(服务)是一个可以在后台执行长时间运行操作而没有用户界面的应用组件,即使当前应用被切换到后台,又或者用户打开了另一个App,服务仍然可以保持正常运行。
BroadCast Receiver
广播接收器是一个用于接收广播信息,并做出对应处理的组件。比如我们常见的系统广播:通知时区改变、电量低、用户改变了语言选项等。开发中我们可以通过继承BroadcastReceiver基类来自定义广播,接收某些我们感兴趣的广播来实现业务需求。
Content Provide
ContentProvider是不同应用程序之间进行数据交换的标准API,ContentProvide以Uri的形式对外提供数据,允许其他应用访问和修改数据;其他应用使用ContentResolve根据Uri进行访问操作指定的数据。

探究activity的生命周期以及启动模式
启动模式 :
1.Standard 标准模式: 每次启动一个Activity都会又一次创建一个新的实例入栈,无论这个实例是否存在。
2.SingleTop 栈顶复用模式 : 要创建的Activity已经处于栈顶时,此时会
直接复用栈顶的Activity。不会再创建新的Activity。
1.SingleTask 栈内复用模式,若须要创建的Activity已经处于栈中时,此时不会创建新的Activity,而是将存在栈中的Activity上面的其他Activity所有销毁,使它成为栈顶。
2.SingleInstance 单实例模式 : 具有此模式的Activity仅仅能单独位于一个任务栈中。
生命周期 :
Java

package com.example.testactivity;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

private Button btn;

@Override
protected void onCreate(Bundle savedInstanceState) {
    Log.i("test","activity1 is created");
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    btn = findViewById(R.id.btn);
    btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent = new Intent(MainActivity.this, MainActivity2.class);
            startActivity(intent);
        }
    });
}

@Override
protected void onStart() {
    Log.i("test","activity1 is started");
    super.onStart();
}

@Override
protected void onResume() {
    Log.i("test", "activity1 is resumeed");
    super.onResume();
}

@Override
protected void onPause() {
    Log.i("test", "activity1 is pauseed");
    super.onPause();
}

@Override
protected void onStop() {
    Log.i("test", "activity1 is stoped");
    super.onStop();
}

@Override
protected void onDestroy() {
    Log.i("test", "activity1 is destroyed");
    super.onDestroy();
}

@Override
protected void onRestart() {
    Log.i("test", "activity1 is Restarted");
    super.onRestart();
}

}

TypeScript

package com.example.testactivity;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;

public class MainActivity2 extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    Log.i("test","activity2 is created");
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main2);
}

@Override
protected void onStart() {
    Log.i("test","activity2 is started");
    super.onStart();
}

@Override
protected void onResume() {
    Log.i("test", "activity2 is resumeed");
    super.onResume();
}

@Override
protected void onPause() {
    Log.i("test", "activity2 is pauseed");
    super.onPause();
}

@Override
protected void onStop() {
    Log.i("test", "activity2 is stoped");
    super.onStop();
}

@Override
protected void onDestroy() {
    Log.i("test", "activity2 is destroyed");
    super.onDestroy();
}

@Override
protected void onRestart() {
    Log.i("test", "activity2 is Restarted");
    super.onRestart();
}

}

单个activity :
启动activity: create start resume
点击返回建 : pause stop destory
点击桌面键: pause stop
多个activity :
启动第一个activity: create start resume
切换到另一个activity : 前一个activity : pause,后一个activity : create start resume ,前一个activity : stop
这个时候分两种情况:
1.点击返回键 : 后一个activity : pause , 前一个activity : restart start resume , 后一个activity : stop destory
2 .点击桌面键 : 后一个activity : pause stop
总结 : 点击返回建,栈顶activity出栈,点击桌面是跳转新的activity,是入栈。
onResume()里面调用finish方法会执行 pause stop destory 等方法。
特殊情况。栈顶是透明activity时,pause -> resume

探究service的生命周期
1.不与activity绑定(左边方式启动)
Java

package com.example.testservice;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

private Button btnStart;
private Button btnStop;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    btnStart = findViewById(R.id.btn_startService);
    btnStop = findViewById(R.id.btn_stopService);
    btnStart.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            startService(new Intent(MainActivity.this,MyService.class));
        }
    });
    btnStop.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            stopService(new Intent(MainActivity.this,MyService.class));
        }
    });
}

}

Java
package com.example.testservice;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

import androidx.annotation.Nullable;

public class MyService extends Service {

private final static String TAG = MyService.class.getSimpleName();

@Override
public void onCreate() {
    super.onCreate();
    Log.d(TAG, "onCreate()...");
}


@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.d(TAG, "onStartCommand()...");
    return super.onStartCommand(intent, flags, startId);
}

@Override
public void onDestroy() {
    super.onDestroy();
    Log.d(TAG, "onDestroy()...");
}

@Override
public IBinder onBind(Intent intent) {
    Log.d(TAG, "onBind()...");
    return null;
}

@Override
public boolean onUnbind(Intent intent) {
    Log.d(TAG, "onUnbind()...");
    return super.onUnbind(intent);
}

}

1.与activity绑定(右边方式启动)
Java

package com.example.testservice;

import androidx.appcompat.app.AppCompatActivity;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;

public class MainActivity2 extends AppCompatActivity {

MyService2 myService2;


private ServiceConnection serviceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        MyService2.LocalBinder binder = (MyService2.LocalBinder) service;//获得自定义的LocalBinder对象
        myService2 = binder.getService();//获得Service对象
    }
    @Override
    public void onServiceDisconnected(ComponentName name) {
        myService2 = null;
    }
};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main2);
    bindService(new Intent(MainActivity2.this,MyService2.class),serviceConnection, Context.BIND_AUTO_CREATE);
}


@Override
protected void onDestroy() {
    unbindService(serviceConnection);
    super.onDestroy();
}

}

Java
package com.example.testservice;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

import androidx.annotation.Nullable;

public class MyService2 extends Service {

private final IBinder binder = new LocalBinder();

private final static String TAG = MyService.class.getSimpleName();



public class LocalBinder extends Binder {
    MyService2 getService(){
        return MyService2.this;
    }
}

@Nullable
@Override
public IBinder onBind(Intent intent) {
    Log.d(TAG, "onBind()......");
    return binder;
}


@Override
public void onCreate() {
    super.onCreate();
    Log.d(TAG, "onCreate()......");
}


@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.d(TAG, "onStartCommand()......");
    return super.onStartCommand(intent, flags, startId);
}

@Override
public void onDestroy() {
    super.onDestroy();
    Log.d(TAG, "onDestroy()......");
}

@Override
public boolean onUnbind(Intent intent) {
    Log.d(TAG, "onUnbind()......");
    return super.onUnbind(intent);
}

}

手动调用方法 作用
startService() 启动服务
stopService() 关闭服务
bindService() 绑定服务
unbindService() 解绑服务
•startService()和stopService()只能开启和关闭Service,无法操作Service; bindService()和unbindService()可以操作Service
•startService()开启的Service,调用者退出后Service仍然存在; bindService()开启的Service,调用者退出后,Service随着调用者销毁。
•如果组件通过调用 startService() 启动服务(这会引起对 onStartCommand() 的调用),则服务会一直运行,直到其使用 stopself() 自行停止运行,或由其他组件通过调用 stopService() 将其停止为止。
•如果组件通过调用 bindService() 来创建服务,且未调用 onStartCommand() ,则服务只会在该组件与其绑定时运行。当该服务与其所有组件取消绑定后,系统便会将其销毁。

不与activity绑定
通过startService方式启动 : create startCommand ,后面再调用startService方法只有 startCommand
通过stopService方式停止 : destroy
与activity绑定
通过bindService方式启动 :create bind
activity销毁的时候里面调用unbindService解绑服务 : unbind destory

探究广播,service通过发送广播与activity通信
Java

package com.example.testbroadcast;

import androidx.appcompat.app.AppCompatActivity;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

MyReceiver receiver ;
private static String ACTION = "123";
private Button btn;

class MyReceiver extends BroadcastReceiver{

    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(MainActivity.this,"我收到消息了!",Toast.LENGTH_LONG).show();
    }
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    btn = findViewById(R.id.btn);
    btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            //  开启  服务
            startService(new Intent(MainActivity.this,MyService.class));
        }
    });
    initReceiver();
}

// 注册  广播接收者
private void initReceiver() {
   receiver = new MyReceiver();
   IntentFilter intentFilter = new IntentFilter();
   intentFilter.addAction(ACTION);
   registerReceiver(receiver,intentFilter);
}

@Override
protected void onDestroy() {
    //  关闭 服务
    stopService(new Intent(MainActivity.this,MyService.class));
    super.onDestroy();
}

}

TypeScript
package com.example.testbroadcast;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

public class MyService extends Service {

private final static String TAG = MyService.class.getSimpleName();

@Override
public void onCreate() {
    super.onCreate();
    Log.d(TAG, "onCreate()...");
}

// 发送  广播   延迟  三秒
private void sendBroad() {
    try {
        Thread.sleep(3000);
    }catch (Exception e) {
        e.printStackTrace();
    }
    Intent intent = new Intent();
    intent.setAction("123");
    sendBroadcast(intent);
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.d(TAG, "onStartCommand()...");
    // 发送  广播
    sendBroad();
    return super.onStartCommand(intent, flags, startId);
}

@Override
public void onDestroy() {
    super.onDestroy();
    Log.d(TAG, "onDestroy()...");
}

@Override
public IBinder onBind(Intent intent) {
    Log.d(TAG, "onBind()...");
    return null;
}

@Override
public boolean onUnbind(Intent intent) {
    Log.d(TAG, "onUnbind()...");
    return super.onUnbind(intent);
}

}
总结 : activity 里面注册广播接收者,service里面发送广播,启动服务后,service发送广播,activity里面的广播接收者接收到后执行对应操作。

Content Provider
•概念(自己的理解)
•通过content provider 来获取联系人列表
•自定义content provider

概念 : 手机里面存取数据通过sqlite来进行,保存在当前程序目录下,content provider相当于是sqlite的外观,当sqlite里面数据改变的时候,content provider里面的notifychange()方法可以实现自动更新。同时content provider可以指定哪些可以被共享,哪些不可以,而sqlite只能全局读取数据。content provider保证了用户的安全与隐私。

通过content provider 来获取联系人列表
Java
package com.example.testcontentprovider;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.Manifest;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;

import android.provider.ContactsContract;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

private String[] columns = {
        ContactsContract.Contacts._ID,// 获得ID值
        ContactsContract.Contacts.DISPLAY_NAME,//获得姓名
        ContactsContract.CommonDataKinds.Phone.NUMBER,//获得电话
        ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
};

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions((Activity) this, new String[]{Manifest.permission.READ_CONTACTS}, 100);
    }
    TextView tv = (TextView) findViewById(R.id.result); //获得布局文件中的标签
    tv.setText(getQueryData());//为标签设置数据
}

private String getQueryData() {
    StringBuilder sb =new StringBuilder();//用于保存字符串
    ContentResolver resolver =getContentResolver();//获得ContentResolver对象
    Cursor cursor =resolver.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);//查询记录

    while(cursor.moveToNext()) {
        int idIndex =cursor.getColumnIndex(columns[0]);//获得ID值的索引
        int displayNameIndex =cursor.getColumnIndex(columns[1]); // 获得姓名索引
        int id =cursor.getInt(idIndex);//获得id
        String displayName =cursor.getString(displayNameIndex);//获得名称
        Cursor phone =resolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, columns[3]+"="+id,
                null, null);
        while(phone.moveToNext()) {
            int phoneNumberIndex =phone.getColumnIndex(columns[2]); // 获得电话索引
            String phoneNumber =phone.getString(phoneNumberIndex); //获得电话
            sb.append(displayName +": "+phoneNumber +"\n");// 保存数据
        }
    }
    cursor.close();//关闭Cursor
    return sb.toString();
}

}
自定义content provider
Java

package com.example.testmycontentprovider;

import androidx.appcompat.app.AppCompatActivity;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

private Button button1;
private Button button2;
private EditText editText1;
private EditText editText2;
private Uri uri = Uri.parse("content://com.example.testmycontentprovider/user");
private final String[] colmuns = {"_id", "name"};
private ListView listView;
private List<String> list = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    button1  = findViewById(R.id.btn1);
    button2  = findViewById(R.id.btn2);
    editText1 = findViewById(R.id.edit1);
    editText2 = findViewById(R.id.edit2);
    button1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Integer  id = Integer.parseInt(editText1.getText().toString());
            String name = editText2.getText().toString();
            if (id!=null && name!=null && !"".equals(name)){
                ContentResolver contentResolver = getContentResolver();
                ContentValues contentValues = new ContentValues();
                contentValues.put("_id",id);
                contentValues.put("name",name);
                contentResolver.insert(uri,contentValues);
            }else {
                Toast.makeText(MainActivity.this,"不能为空",Toast.LENGTH_LONG).show();
            }
        }
    });

    button2.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            ContentResolver resolver = getContentResolver();
            Cursor cursor = resolver.query(uri, colmuns, null, null, null, null);
            while (cursor.moveToNext()) {
                int idIndex = cursor.getColumnIndex(colmuns[0]);
                int nameIndex = cursor.getColumnIndex(colmuns[1]);
                String id = String.valueOf(cursor.getString(idIndex));
                String name = cursor.getString(nameIndex);
                list.add(id + " : " + name);
            }
            cursor.close();
            listView = findViewById(R.id.listview);
            listView.setAdapter(new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_dropdown_item_1line, list));
        }

    });


}

}

TypeScript
package com.example.testmycontentprovider;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

public class MyContentProvider extends ContentProvider
{
private SQLiteOpenHelper dataBaseHelper;
private SQLiteDatabase db;

public static final String AUTHORITY = "com.example.mycontentprovider";

// 设置ContentProvider的唯一标识
public static final int User_Code = 1;

// UriMatcher类使用:在ContentProvider 中注册URI
private static final UriMatcher uriMatcher;
static{
    uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    // 初始化
    uriMatcher.addURI(AUTHORITY,"user", User_Code);
}

@Override
public boolean onCreate() {
    dataBaseHelper = MySqLiteHelper.getmInstance(getContext());
    db = dataBaseHelper.getWritableDatabase();
    return true;
}

@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
    return db.query("user",projection,selection,selectionArgs,null,null,sortOrder,null);
}

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

@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
    db.insert("user",null,values);
    return uri;
}

@Override
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
    return 0;
}

@Override
public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
    return 0;
}

}

Java
package com.example.testmycontentprovider;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import androidx.annotation.Nullable;

public class MySqLiteHelper extends SQLiteOpenHelper {

private static String USER_TABLE = "user";

private static SQLiteOpenHelper mInstance;


public static synchronized SQLiteOpenHelper getmInstance(Context context){
    if (mInstance == null){
        mInstance = new MySqLiteHelper(context,"my.db",null,1);
    }
    return mInstance;
}

public MySqLiteHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
    super(context, name, factory, version);
}

//  数据库初始化的时候调用   创建表 只调用一次
@Override
public void onCreate(SQLiteDatabase db) {
    String sql = "create table user(_id integer primary key autoincrement,name text)";
    db.execSQL(sql);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

}

}

横竖屏切换生命周期
加载竖屏:
I/test: activity1 is created
I/test: activity1 is started
I/test: activity1 is resumeed
竖屏切换到横屏:
I/test: activity1 is pauseed
I/test: activity1 is stoped
I/test: activity1 is destroyed
I/test: activity1 is created
I/test: activity1 is started
I/test: activity1 is resumeed

在AndroidManifest.xml中设置

竖屏切换到横屏就不会再走生命周期,而是执行onConfigurationChanged方法,仍然会进行横竖屏切换。但是不会设置横屏的布局。仍然是竖屏布局,仅仅只是横屏显示 。
TypeScript
//屏幕方向发生改变的回调方法
@Override
public void onConfigurationChanged(Configuration newConfig) {

if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        text_screen.append("\n 当前屏幕为横屏");
    } else {
        text_screen.append("\n 当前屏幕为竖屏");
    }
    super.onConfigurationChanged(newConfig);
    Log.e("TAG", "onConfigurationChanged");
  //  setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);  //设置横屏
}

(一)设置屏幕横屏代码
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
这个在Activity下可以直接使用
(二)设置屏幕竖屏的代码
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
(三)判断屏幕是横屏还是竖屏的状态
/**
*系统中定义: int ORIENTATION_PORTRAIT = 1; 竖屏
*系统中定义: int ORIENTATION_LANDSCAPE = 2; 横屏
*/
//获取屏幕的方向 ,数值1表示竖屏,数值2表示横屏
int screenNum = getResources().getConfiguration().orientation;

layout-land文件夹下面是加载横屏布局模式

Android窗口几种 安卓窗口组件_Android窗口几种