6、Android Activity
活动代表了一个具有用户界面的单一屏幕,如 Java 的窗口或者帧。
如果你曾经用 C,C++ 或者 Java 语言编程,你应该知道这些程序从 main() 函数开始。很类似的,Android 系统初始化它的程序是通过活动中的 onCreate() 回调的调用开始的。存在有一序列的回调方法来启动一个活动,同时有一序列的方法来关闭活动,如下面的活动声明周期图所示:
Activity生命周期
方法 | 描述 |
---|---|
onCreate() | 这是第一个回调,在活动第一次创建时调用。 |
onStart() | 这个回调在活动为用户可见时被调用。 |
onResume() | 这个回调在应用程序与用户开始可交互的时候调用。 |
onPause() | 被暂停的活动无法接受用户输入,不能执行任何代码。当前活动将要被暂停,上一个活动将要被恢复时调用。 |
onStop() | 当活动不在可见时调用。 |
onDestroy() | 当活动被系统销毁之前调用。 |
onRestart() | 当活动被停止以后重新打开时调用。 |
package com.example.helloworld;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
public class MainActivity extends Activity {
String msg = "Android : ";
/** 当活动第一次被创建时调用 */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(msg, "The onCreate() event");
}
/** 当活动即将可见时调用 */
@Override
protected void onStart() {
super.onStart();
Log.d(msg, "The onStart() event");
}
/** 当活动可见时调用 */
@Override
protected void onResume() {
super.onResume();
Log.d(msg, "The onResume() event");
}
/** 当其他活动获得焦点时调用 */
@Override
protected void onPause() {
super.onPause();
Log.d(msg, "The onPause() event");
}
/** 当活动不再可见时调用 */
@Override
protected void onStop() {
super.onStop();
Log.d(msg, "The onStop() event");
}
/** 当活动将被销毁时调用 */
@Override
public void onDestroy() {
super.onDestroy();
Log.d(msg, "The onDestroy() event");
}
}
7、Android Service
服务是一个后台运行的组件,执行长时间运行且不需要用户交互的任务。即使应用被销毁也依然可以工作。服务基本上包含两种状态:
- Started,Android的应用程序组件,如活动,通过startService()启动了服务,则服务是Started状态。一旦启动,服务可以在后台无限期运行,即使启动它的组件已经被销毁。
- Bound,当Android的应用程序组件通过bindService()绑定了服务,则服务是Bound状态。Bound状态的服务提供了一个客户服务器接口来允许组件与服务进行交互,如发送请求,获取结果,甚至通过IPC来进行跨进程通信。
左图展示了当服务通过startService()被创建时的生命周期。右图显示了当服务通过bindService()被创建时的生命周期。
两种启动方式的比较
start方式
特点:一旦服务开启跟调用者(开启者)就没有任何关系了。开启者退出了,开启者挂了,服务还在后台长期的运行。开启者不能调用服务里面的方法。
bind方式
特点:bind的方式开启服务,绑定服务,调用者挂了,服务也会跟着挂掉。绑定者可以调用服务里面的方法。
Service生命周期
方法 | 描述 |
---|---|
onStartCommand() | 其他组件(如活动)通过调用startService()来请求启动服务时,系统调用该方法。如果你实现该方法,你有责任在工作完成时通过stopSelf()或者stopService()方法来停止服务。 |
onBind() | 当其他组件想要通过bindService()来绑定服务时,系统调用该方法。如果你实现该方法,你需要返回IBinder对象来提供一个接口,以便客户来与服务通信。你必须实现该方法,如果你不允许绑定,则直接返回null。 |
onUnbind() | 当客户中断所有服务发布的特殊接口时,系统调用该方法。 |
onRebind() | 当新的客户端与服务连接,且此前它已经通过onUnbind(Intent)通知断开连接时,系统调用该方法。 |
onCreate() | 当服务通过onStartCommand()和onBind()被第一次创建的时候,系统调用该方法。该调用要求执行一次性安装。 |
onDestroy() | 当服务不再有用或者被销毁时,系统调用该方法。你的服务需要实现该方法来清理任何资源,如线程,已注册的监听器,接收器等。 |
package com.runoob.androidservices;
import android.app.Service;
import android.os.IBinder;
import android.content.Intent;
import android.os.Bundle;
public class HelloService extends Service {
/** 标识服务如果被杀死之后的行为 */
int mStartMode;
/** 绑定的客户端接口 */
IBinder mBinder;
/** 标识是否可以使用onRebind */
boolean mAllowRebind;
/** 当服务被创建时调用. */
@Override
public void onCreate() {
}
/** 调用startService()启动服务时回调 */
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return mStartMode;
}
/** 通过bindService()绑定到服务的客户端 */
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
/** 通过unbindService()解除所有客户端绑定时调用 */
@Override
public boolean onUnbind(Intent intent) {
return mAllowRebind;
}
/** 通过bindService()将客户端绑定到服务时调用*/
@Override
public void onRebind(Intent intent) {
}
/** 服务不再有用且将要被销毁时调用 */
@Override
public void onDestroy() {
}
}
8、Intent and Filter
Intent
四大组件沟通的桥梁。
显式意图
这些意图通过名称指定目标组件,一般用于应用程序内部信息 - 比如一个活动启动一个下属活动或者启动一个兄弟活动(例如:指定点击跳转的目标,跳转到浏览器或者拨打电话等)。
// 通过指定类名的显式意图
Intent i = new Intent(FirstActivity.this, SecondAcitivity.class);
// 启动目标活动
startActivity(i);
隐式意图
这些意图没有为目标命名,组件名称的域为空。隐式意图经常用于激活其他应用程序的组件。
Intent read1=new Intent();
read1.setAction(android.content.Intent.ACTION_VIEW);
read1.setData(ContactsContract.Contacts.CONTENT_URI);
startActivity(read1);
Filter
Android 操作系统使用过滤器来指定一系列活动、服务和广播接收器处理意图,需要借助于意图所指定的动作、类别、数据模式。
在 manifest 文件中使用 <intent-filter> 元素在活动,服务和广播接收器中列出对应的动作,类别和数据类型。下面的实例展示AndroidManifest.xml文件的一部分,指定一个活动com.runoob.intentfilter.CustomActivity可以通过设置的动作,类别及数据来调用:
<activity android:name=".CustomActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<action android:name="com.example.MyApplication.LAUNCH" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http" />
</intent-filter>
</activity>
上面的实例中,自定义活动期望的数据由"http://"开头。有这样的情况,通过过滤器,意图将被传递到多个的活动或者服务,用户将被询问启动哪个组件。如果没有找到目标组件,将发生一个异常(很抱歉,“***已停止运行”)。
9、Android Broadcast Receivers
广播接收器用于响应来自其他应用程序或者系统的广播消息。这些消息有时被称为事件或者意图。
有以下两个重要的步骤来使系统的广播意图配合广播接收器工作:
- 创建广播接收器
- 注册广播接收器
- 还有一个附加的步骤,要实现自定义的意图,必须创建并广播这些意图。
创建广播接收器
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Intent Detected.", Toast.LENGTH_LONG).show();
}
}
注册广播接收器
该事件由Android系统的启动进程完成时发出。
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<receiver android:name="MyReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED">
</action>
</intent-filter>
</receiver>
</application>
现在,无论什么时候Android设备被启动,都将被广播接收器MyReceiver所拦截,并且在onReceive()中实现的逻辑将被执行。
广播自定义意图
如果你想要应用程序中生成并发送自定义意图,你需要在活动类中通过sendBroadcast()来创建并发送这些意图。如果你使用sendStickyBroadcast(Intent)方法,则意图是持久的(sticky),这意味着你发出的意图在广播完成后一直保持着。
public void broadcastIntent(View view)
{
Intent intent = new Intent();
intent.setAction("com.runoob.CUSTOM_INTENT");
sendBroadcast(intent);
}
10、Android Content Provider
内容提供者组件通过请求从一个应用程序向其他的应用程序提供数据。这些请求由类 ContentResolver 的方法来处理。内容提供者可以使用不同的方式来存储数据。数据可以被存放在数据库,文件,甚至是网络。(在通信录demo中会使用到内容提供者)
内容提供者可以让内容集中,必要时可以有多个不同的应用程序来访问。内容提供者的行为和数据库很像。你可以查询,编辑它的内容,使用 insert(), update(), delete() 和 query() 来添加或者删除内容。多数情况下数据被存储在 SQLite 数据库。
内容URL
<prefix>://<authority>/<data_type>/<id>
部分 | 说明 |
---|---|
prefix | 前缀:一直被设置为content:// |
authority | 授权:指定内容提供者的名称,例如联系人,浏览器等。第三方的内容提供者可以是全名,如:cn.programmer.statusprovider |
data_type | 数据类型:这个表明这个特殊的内容提供者中的数据的类型。例如:你要通过内容提供者Contacts来获取所有的通讯录,数据路径是people,那么URI将是下面这样:content://contacts/people |
id | 这个指定特定的请求记录。例如:你在内容提供者Contacts中查找联系人的ID号为5,那么URI看起来是这样:content://contacts/people/5 |
创建内容提供者
这里描述了创建自己的内容提供者的简单步骤。
- 首先,你需要继承类 ContentProviderbase 来创建一个内容提供者类。
- 其次,你需要定义用于访问内容的你的内容提供者URI地址。
- 接下来,你需要创建数据库来保存内容。通常,Android 使用 SQLite 数据库,并在框架中重写 onCreate() 方法来使用 SQLiteOpenHelper 的方法创建或者打开提供者的数据库。当你的应用程序被启动,它的每个内容提供者的 onCreate() 方法将在应用程序主线程中被调用。
- 最后,使用<provider.../>标签在 AndroidManifest.xml 中注册内容提供者。
Content Provider生命周期
- onCreate():当提供者被启动时调用。
- query():该方法从客户端接受请求。结果是返回指针(Cursor)对象。
- insert():该方法向内容提供者插入新的记录。
- delete():该方法从内容提供者中删除已存在的记录。
- update():该方法更新内容提供者中已存在的记录。
- getType():该方法为给定的URI返回元数据类型。
11、Android Fragment
碎片是活动的一部分,使得活动更加的模块化设计。我们可以认为碎片是一种子活动。
- 碎片拥有自己的布局,自己的行为及自己的生命周期回调。
- 当活动在运行的时候,你可以在活动中添加或者移除碎片。
- 你可以合并多个碎片在一个单一的活动中来构建多栏的UI。
- 碎片可以被用在多个活动中。
- 碎片的生命周期和它的宿主活动紧密关联。这意味着活动被暂停,所有活动中的碎片被停止。
- 碎片可以实现行为而没有用户界面组件。
- 碎片是 Android API 版本11中被加入到 Android API。
当运行在在平板尺寸的设备上,这个应用程序可以在活动A中嵌入两个碎片。在手机设备屏幕上,由于没有足够的空间,活动A仅包含有文章列表的碎片,当用户点击文章时,启动包含第二个碎片的活动B来阅读文章。
Fragment生命周期
- onAttach(): 碎片实例被关联到活动实例。碎片和活动还没有完全初始化。通常,你在该方法中获取到活动的引用,在碎片将来的初始化工作中被使用。
- onCreate(): 当创建碎片时,系统调用该方法。你需要初始化一些碎片的必要组件。这些组件是当碎片被暂停、停止时需要保留的,以便被恢复。
- onCreateView(): 当碎片将要第一次绘制它的用户界面时系统调用该方法。为了绘制碎片的UI,你需要从该方法中返回一个代表碎片根布局的View组件。如果该碎片不提供用户界面,直接返回null。
- onActivityCreated: 当宿主活动被创建,在onCreateView()方法之后调用该方法。活动和碎片实例与活动的视图层级被创建。这时,视图可以通过findViewById()方法来访问。在这个方法中,你可以实例化需要Context对象的对象。
- onStart(): 碎片可见时调用该方法。
- onResume(): 碎片可交互时调用该方法。
- onPause(): 当首次表明用户将要离开碎片时系统调用该方法。通常,这里你需要提交任何的会超出用户会话的持久化的变化。
- onStop(): 碎片将要被停止时调用。
- onDestroyView(): 调用该方法后,碎片将要被销毁。
- onDestroy(): 该方法被用来清理碎片的状态。但在Android平台并不保证一定被调用。
碎片类型
基本的碎片可以分为如下所示的三种:
- 单帧碎片,单帧碎片被如移动电话之类的手持设备使用。一个碎片如同一个视频一样显示。
- 列表碎片,包含有特殊列表视图的碎片被叫做列表碎片。
- 碎片过度,与碎片事务一起使用。可以从一个碎片移动到另外一个碎片。
如何使用碎片
这里介绍创建碎片的简单步骤。
- 首先决定在活动中需要使用多少个碎片。例如,我们需要使用两个碎片来处理设备的横屏和竖屏两种模式。
- 下一步,基于碎片数量,创建继承自类Fragment的类。类Fragment包含上面提到的回调函数。根据你的需求重写任意的方法。
- 对应每个片段,你需要在XML文件中创建布局。这些文件中包含已定义的碎片的布局。
- 最后,基于需求修改活动文件来定义实际的碎片替换逻辑。
参考文档:
Android 教程 | 菜鸟教程
Android移动开发基础第二版-课后习题_android移动开发基础答案_Ipkiss工作室的博客-CSDN博客
Android中服务(Service)的两种启动方式_安卓service两种服务方式_十一多一点。的博客-CSDN博客