服务(Service)和内容提供器(Content Provider)的介绍。

服务(Service)

服务:长期后台运行的没有界面的组件。
使用场景:后台连接服务器的逻辑,例如:每隔一段时间,获得最新的天气信息。
长期在后台运行的组件,不要在 Activity 开启子线程,应该是创建服务,在服务里开启子线程。

Android 系统进程管理是按照一定的规则:

  1. 应用程序一旦打开,通常情况下关闭(清空任务栈)后进程不会停止,方便下一次快速启动,带来内存不足的问题;
  2. Android系统有一套内存清理机制,按照优先级回收系统内存;
  3. 进程分为5个等级的优先级。
  • Foreground process(前台进程,用户正在用的应用程序对应的进程)
  • Visible process(可见进程,用户仍然可以看到这个进程的界面)
  • Service process(服务进程,应用程序有一个服务组件在后台运行)
  • Background process(后台进程,应用程序没有服务在进行,并且最小化)
  • Empty process(空进程,没有任何运行的Activity,任务栈空了)

服务的目的:

  1. 长期在后台运行;
  2. 提高进程的优先级,系统不容易回收进程,即便回收了,内存充足的时候,把进程重新创建。

使用服务的方式:

  1. 开始服务,停止服务
    onCreate()   //创建时调用
    onStartCommand() //开始时调用 (如果服务已经开启,不会再调用onCreate() 方法,而是调用onStartCommand())
    onDestroy() //销毁时调用
    服务只会被停止一次
  2. 绑定服务,解绑服务
    onCreate()   //创建时调用
    onBind() //在绑定时候调用
    onunbind() //在解绑的时候调用
    onDestory() //销毁时调用

区别:

  1. start(也就是第一种方式)方式服务,一旦服务开启跟调用者(开启者)没有任何关系了,开启者退出了,服务还在后台长期的运行
  2. 开启者没有办法调用服务里面的办法
  3. bind的方式开启服务,绑定服务,调用者挂了,服务也会跟着挂掉
  4. 开启者可以调用服务里面的方法

本地服务:调用者和服务在同一个工程代码里
远程服务:调用者和服务在不同的工程代码里面

每个应用程序都是运行在自己独立的进程里面;进程操作系统分配内存空间的一个单位,进程的数据都是独立的,独立的内存空间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class MyService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}

//服务创建时调用
@Override
public void onCreate() {
super.onCreate();
}


//服务启动时调用,服务一旦启动就立刻执行某个动作,就可以将逻辑写在onStartCommand里
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}

//服务销毁时调用
@Override
public void onDestroy() {
super.onDestroy();
}
}

内容提供器(Content Provider)

两种用法

  1. 使用现有的内容提供器来读取和操作相应程序中的数据(使用场景:获取系统自带的的联系人信息,图片库,音频库等);
  2. 创建自己的内容提供器给 我们程序的数据提供外部访问接口。

ContentResolver的基本用法
增删改查:
insert()
updata()
delete()
query()

image.png

查询完成之后返回的的是Cursor对象,读取思路通过移动游标遍历Cursor所有行,然后取出每一行相应数据

demo:读取系统联系人

  1. 在模拟器中创建 2 个联系人+电话号码(用于后面读取数据);
  2. 在xml文件中添加一个 ListView;
  3. 修改 MainActivity 代码;
  4. 在 AndroidManifest.xml 文件中添加权限。
1
<uses-permission android:name="android.permission.READ_CONTACTS"></uses-permission>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public class MainActivity extends AppCompatActivity {

ListView list_view;
ArrayAdapter<String> adapter;
List<String> contactsList = new ArrayList<String>();



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

list_view = (ListView)findViewById(R.id.list_view);

//传入的data为contactsList
adapter = new ArrayAdapter<String>(this ,android.R.layout.simple_list_item_1 , contactsList);
list_view.setAdapter(adapter);

//获取listview,设置适配器后,调用readContacts方法
readContacts();
}
private void readContacts(){

//初始化cursor为空
Cursor cursor = null;

// 为cursor赋值
try {
cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);

//对cursor进行遍历,取出联系人和手机号
while (cursor.moveToNext()){
String displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));

//拼接的数据加上换行,添加到listview中
contactsList.add(displayName +"\n" +number);
}
adapter.notifyDataSetChanged();
}catch(Exception e){
e.printStackTrace();
}finally {
if (cursor != null){
cursor.close();
}
}

}
}