一、Activity
在应用程序中至少包含一个用来处理应用程序的主UI功能的主界面屏幕。这个主界面一般由多个Fragment组成,并由一组次要Activity支持。要在屏幕之间切换,就必须要启动一个新的Activity。一般的Activity都占据了整个显示屏,但可以创建成半透明或二者浮动的Activity。
1、Activity的创建
通过继承Activity类可以创建一个Activity窗口,基本框架如下:
public class MyActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
以上代码是一个空的Activity,可以通过使用Fragment、布局和视图来创建UI。视图是用来显示数据和提供交互交互的UI控件。Android提供给了多个布局类,成为ViewGroup,它可以包含多个视图来帮助UI布局。Fragment用来封装UI的各个部分,从而能够方便的创建动态界面,这些界面能够针对不同的屏幕尺寸很方向重新排列,起到优化UI的效果。
要想把一个UI分配给一个Activity,需要在onCreate()方法中调用setContentView()方法。可以通过在java代码中创建布局,也可以通过调用xml布局资源文件来创建。如下两种方式:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView tvShow = new TextView(this);
setContentView(tvShow);
tvShow.setText("你好");
}
当然,通过调用xml布局文件来创建UI的方法更常用,如下:protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
最后,创建好了Activity类不要忘了在Manifest中对其注册。
需要注意的是,想让一个Activity可以被应用程序启动器使用,它必须包含一个监听MAIN动作和LAUNCHER分类的Intent-Filter,如下:
<activity
android:name="com.codingblock.myactivity.MyActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
2、Activity的生存周期
(1)Activity栈:每一个Activity的状态是由他在Activity栈中所处的位置所决定的,Activity栈是当前所有正在运行的Activity的后进先出的集合。当一个新Activity启动,它就会变成Activity状态,并移到栈顶,当返回到前一个Activity,前台Activity被关闭,那么站总的下一个Activity就会移动到栈顶,变成活动状态。
(2)Activity状态
随着Activity的创建和销毁,从栈中移进移出的过程中他们经历了如下4种可能的状态:
· 活动状态:当一个Activity处于栈顶是,它是可见的、具有焦点的前台Activity并可以接受用户输入。
· 暂停状态:Activity可见,但没有焦点,不能接受用户输入事件。(例如:当一个透明的或者非全屏的Activity位于该Activity之前时)
· 停止状态:Activity不可见。此时,Activity仍然会保留在内存中,保存所有状态信息,然而当系统的其他地方要求使用使用内存时,会优先终止此类状态的Activity。
· 非活动状态:Activity被终止。此时Activity已经从栈中移除了。
(3)监控状态改变
为了保证Activity可以对状态改变做出反应,Android提供了一系列的回调方法,当Activity的状态改变时它们就会被触发。以下代码是整个Activity生存期的框架,各方法的说明已在代码注释中详细给出:
public class MyActivity extends Activity {
//在完整生存期开始调用
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//初始化Activity并填充UI
}
//在onCreate方法完成后调用,用于恢复UI状态
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
/*
* 从savedInstanceState恢复UI状态
* 这个Bundle也被传递给了onCreate
* 自Activity上次可见之后,只有系统终止了该Activity时,才会被调用
*/
}
//在随后的Activity进程可见生存期之前调用
@Override
protected void onRestart() {
super.onRestart();
//加载改变,知道Activity在此进程中已经可见
}
//在可见生存期的开始时调用
@Override
protected void onStart() {
super.onStart();
//既然Activity可见,就应用任何要求的UI Change
}
//在Activity状态生存期开始时调用
@Override
protected void onResume() {
super.onResume();
/*
* 恢复Activity需要,但是当它处于不活动状态时被挂起的暂停的UI更新、线程或进程
* 在Activity状态生命周期结束的时候滴啊用,用来保存UI状态的改变
*/
}
//在UI状态改变保存到saveInstanceState
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
/*
* 如果进程被运行时终止并被重启,
* 那么这个Bundle将被传递给onCreate和onRestoreInstanceState
*/
}
//在Activity状态生存期结束时调用
@Override
protected void onPause() {
super.onPause();
/*
* 挂起不需要更新的UI更新、线程或者CPU密集的进程
* 当Activity不是前台的活动状态的Activity时
*/
}
//在可见生存期结束时调用
@Override
protected void onStop() {
super.onStop();
/*
* 挂起不需要的UI更新、线程或处理
* 当Activity不可见时,保存所有的编辑或者状态改变,因为在调用这个方法后,京城可能会被终止
*/
}
//在完整生存期结束时调用
@Override
protected void onDestroy() {
super.onDestroy();
/*
* 清理所有的资源,包括结束线程、
* 关闭数据库连接等
*/
}
}
二、Service
1、Service的创建
在创建Service时,步骤与Activity很像:
1.继承Service,创建Service子类。
2.在AndroidManifest.xml文件中配置该Service。
下面创建一个最基本的Service组件:MyService.java
public class MyService extends Service {
//必须实现的方法,用户返回Binder对象
@Override
public IBinder onBind(Intent intent) {
System.out.println("--onBind()--");
return null;
}
//创建Service时调用该方法,只调用一次
@Override
public void onCreate() {
super.onCreate();
System.out.println("--onCreate()--");
}
//每次启动Servcie时都会调用该方法
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("--onStartCommand()--");
return super.onStartCommand(intent, flags, startId);
}
//解绑Servcie调用该方法
@Override
public boolean onUnbind(Intent intent) {
System.out.println("--onUnbind()--");
return super.onUnbind(intent);
}
//退出或者销毁时调用该方法
@Override
public void onDestroy() {
System.out.println("--onDestroy()--");
super.onDestroy();
}
}
然后再Manifest.xml文件中红配置一下
<service
android:name=".MyService">
</service>
为了待会测试的方便,我们在该Service的onCreate()方法里面写一个方法,开启一个线程,让其不断输出“Service运行中”的状态。补充后的MyService类如下:
public class MyService extends Service {
private boolean serviceRunning = false;
// 必须实现的方法,用户返回Binder对象
@Override
public IBinder onBind(Intent intent) {
System.out.println("--onBind()--");
return null;
}
// 创建Service时调用该方法,只调用一次
@Override
public void onCreate() {
super.onCreate();
System.out.println("--onCreate()--");
serviceRunning = true;
new Thread() {
@Override
public void run() {
while (serviceRunning) {
System.out.println("---Service运行中---");
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
}.start();
}
// 每次启动Servcie时都会调用该方法
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("--onStartCommand()--");
return super.onStartCommand(intent, flags, startId);
}
// 解绑Servcie调用该方法
@Override
public boolean onUnbind(Intent intent) {
System.out.println("--onUnbind()--");
return super.onUnbind(intent);
}
// 退出或者销毁时调用该方法
@Override
public void onDestroy() {
serviceRunning = false;
System.out.println("--onDestroy()--");
super.onDestroy();
}
}
代码分析:首先我们定义一个boolean类型的变量serviceRunning,用来控制新线程中是否输出“---Service运行中---”,通过这样的方式更能让我们直观地看到Servcie的运行状态。
2、启动Service
启动Service和启动一个Activity类似,也是先定义一个Intent让它指向需要启动Service,然后通过调用startService()方法,启动即可,具体代码如下:
btn_start_service.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
intent = new Intent(this, MyService.class);
startService(intent);
}
});
代码分析:在主界面中添加了一个按钮,在按钮中首先定义了一个Intent,然后通过startService启动该Intent从而就可以启动Service,与启动一个Activity的方法一模一样。
3、停止Service
与启动Service相对应的就是停止Service,通过stopService()即可完成此操作,如下:btn_stop_service.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
stopService(intent);
}
});
当然,这里Intent需要与startService使用的为一个。
4、绑定Service
绑定Service用是通过调用bindService(Intent service, ServiceConnection conn, int flags)方法来实现的,单看参数就知道与启动Service比起来,会麻烦一些,大体分为如下三步:
第一步:重写onBind()方法,返回Service实例
Service可以让Activity绑定,以获得更加详细的接口。如果先想让一个Service支持绑定,需要实现Service中得onBind()方法,并返回被绑定Service的当前实例,如下:
public IBinder onBind(Intent intent) {
System.out.println("--onBind()--");
return new MyBinder();
}
public class MyBinder extends Binder{
MyService getService(){
return MyService.this;
}
第二步:实现一个ServiceConnection 另外,Service和其他组件的链接表示为一个ServiceConnection,要想一个Service和其他组件绑定,需要实现一个新的ServiceConnection,建立一个链接后,就可以通过重写onServiceConnected()方法和onServiceDisconnected()方法,来获得对Service实例的引用。代码如下:
MyService.MyBinder binder = null;
class MyServiceConn implements ServiceConnection {
// 服务被绑定成功之后执行
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//service为onBind方法返回的Service实例
binder = (MyService.MyBinder) service;
}
// 服务奔溃或者被杀掉执行
@Override
public void onServiceDisconnected(ComponentName name) {
binder = null;
}
}
第三步:调用bindService执行绑定Service
要想绑定需要给bindService()除了需要给他传递一个需要的Intent和一个ServiceConnection实例外,还需要指定一个标示,如下:
btn_bind_service.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
bindService(intent, myServiceConn, Context.BIND_AUTO_CREATE);
}
});
其中,myServiceConn为第二步中MyServiceConn实例,Context.BIND_AUTO_CREATE即为标示。
5、解绑Service
解绑Service是通过unbindService实现的,如下:
btn_unbind_service.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
if (binder != null) {
unbindService(myServiceConn);
}
}
});
这里需要注意的是,unbindService方法中传入的ServiceConnection实例一定要跟绑定时的一致,否则可能会导致程序崩溃。