1 类图
在【FJU项目】1像素进程保活(二)中,涉及到的几个类的类图如下所示(仅供参考):
实线箭头:关联
虚线箭头:依赖
2 代码分析
2.1 之前的OnePixelManager类源码如下:
package com.yds.jianshu.onepixel;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import java.lang.ref.WeakReference;
public class OnePixelManager {
private static final String TAG = "[OnePixelManager]";
private WeakReference mActivity;
private OnePixelReceiver onePixelReceiver;
/**
* 一像素广播接收者注册方法。该方法中初始化OnePixelReceiver,并添加了过滤条件
* 屏幕息屏和亮屏。然后注册该广播接收者
* @param context
*/
public void registerOnePixelReceiver(Context context){
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
onePixelReceiver = new OnePixelReceiver();
context.registerReceiver(onePixelReceiver,filter);
}
/**
* 对广播接收者进行解注册
* @param context
*/
public void unregisterOnePixelReceiver(Context context){
if (null != onePixelReceiver){
context.unregisterReceiver(onePixelReceiver);
}
}
/**
* 开启一像素Activity
* @param context
*/
public void startOnePixelActivity(Context context){
Intent intent = new Intent();
intent.setClass(context,OnePixelActivity.class);
context.startActivity(intent);
}
/**
* 关闭一像素Activity
*/
public void finishOnePixelActivity(){
if(null!=mActivity){
Activity activity = mActivity.get();
if(null!=activity){
activity.finish();
}
mActivity = null;
}
}
/**
* 使用弱引用获取一像素的上下文
* @param activity
*/
public void setKeepAliveReference(OnePixelActivity activity){
mActivity = new WeakReference(activity);
}
}
上述代码中,总共有5个方法,但是职责却不是单一的,上述方法的作用如下:
-
registerOnePixelReceiver
:一像素广播接收者注册方法。该方法中初始化OnePixelReceiver,并添加了过滤条件屏幕息屏和亮屏。然后注册该广播接收者 -
unregisterOnePixelReceiver
:对广播接收者进行解注册 -
startOnePixelActivity
:开启一像素Activity -
finishOnePixelActivity
:关闭一像素Activity -
setKeepAliveReference
:使用弱引用获取一像素的上下文
上述可以大致分为两个职责,一个是对Activity进行管理,一个是对广播接收者进行管理,但上述代码将其封装到了一个类中,不利于扩展,且耦合度比较高。所以可以将其拆分成两个管理类,一个用于管理Activity的ActivityManager,一个用于管理Receiver的ReceiverManager类。
2.2 写一个Manager接口,预留后用
package com.yds.jianshu.itf;
/**
* Created by yds
* on 2019/8/2.
*/
public interface Manager {
//预留接口
}
- 写一个抽象ActivityManager类
package com.yds.jianshu.manager;
import android.app.Activity;
import android.content.Context;
import com.yds.jianshu.itf.Manager;
import com.yds.jianshu.utils.ObjectUtil;
/**
* Created by yds
* on 2019/8/2.
*/
public abstract class ActivityManager implements Manager {
public abstract void startActivity(Context context);
public void finishActivity(Activity activity){
ObjectUtil.requireNonNull(activity,"activity is null");
activity.finish();
}
}
一般Activity有两种最常用的行为,一个是开启Activity,一个是关闭Activity,开启Activity可以根据其需求写具体的代码,所以这里将其设置为抽象类型,关闭Activity几乎是通用的,这里就在抽象类里实现。
2.3 具体的Activity管理类OnePixelActivityManager
package com.yds.jianshu.manager;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import com.yds.jianshu.onepixel.OnePixelActivity;
import com.yds.jianshu.utils.ObjectUtil;
import java.lang.ref.WeakReference;
/**
* Created by yds
* on 2019/8/2.
*/
public class OnePixelActivityManager extends ActivityManager {
private WeakReference mActivity;
/**
* 将{@link OnePixelActivity}的引用保存起来,用于后面监测到屏幕亮时关闭{@link OnePixelActivity},
* 使用弱引用,是因为如果O{@link OnePixelActivity}被回收了,那么就不需要再保存该对象的引用用于
* finish了
* @param activity
*/
public void registerActivityReference(Activity activity){
ObjectUtil.requireNonNull(activity,"activity is null");
mActivity = new WeakReference(activity);
}
@Override
public void startActivity(Context context) {
ObjectUtil.requireNonNull(context,"context is null");
Intent intent = new Intent();
intent.setClass(context, OnePixelActivity.class);
context.startActivity(intent);
}
public void finishOnePixelActivity(){
ObjectUtil.requireNonNull(mActivity,"mActivity is null");
Activity activity = mActivity.get();
ObjectUtil.requireNonNull(activity,"activity is null");
finishActivity(activity);
mActivity = null;
}
}
2.4 用于管理BroadcastReceiver的类
package com.yds.jianshu.manager;
import android.content.BroadcastReceiver;
import android.content.Context;
import com.yds.jianshu.itf.Manager;
/**
* Created by yds
* on 2019/8/2.
*/
public abstract class ReceiverManager implements Manager {
public BroadcastReceiver receiver;
public abstract void register(Context context);
public abstract void unregister(Context context);
public void createReceiver(BroadcastReceiver receiver){
this.receiver = receiver;
}
}
广播接收者一般有两个行为,一个是注册,一个是取消注册。因为注册和取消注册,都需要创建具体的Receiver实例,所以可以将其提取到父类中。
2.5 用于管理1像素receiver的OnePixelReceiverManager
package com.yds.jianshu.manager;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import com.yds.jianshu.onepixel.OnePixelReceiver;
import com.yds.jianshu.utils.ObjectUtil;
/**
* Created by yds
* on 2019/8/2.
*/
public class OnePixelReceiverManager extends ReceiverManager {
public OnePixelReceiverManager(){
createReceiver(new OnePixelReceiver());
}
@Override
public void register(Context context) {
ObjectUtil.requireNonNull(context,"context is null");
ObjectUtil.requireNonNull(receiver,"receiver is null");
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
context.registerReceiver(receiver,filter);
}
@Override
public void unregister(Context context) {
ObjectUtil.requireNonNull(context,"context is null");
ObjectUtil.requireNonNull(receiver,"receiver is null");
context.unregisterReceiver(receiver);
}
}
上述代码符合单一职责原则
,单一职责原则有如下定义:
单一职责原则
:一个对象应该只包含单一的职责,并且该职责被完整封装在一个类中。
上述OnePixelReceiverManager符合单一职责,它主要是对OnePixelReceiver进行相关操作管理;OnePixelActivityManager 也符合单一职责,它主要是对OnePixelActivity进行相关管理。
上述代码中,有这么一段代码:
public class OnePixelReceiverManager extends ReceiverManager {
public OnePixelReceiverManager(){
createReceiver(new OnePixelReceiver());
}
}
public abstract class ReceiverManager implements Manager {
public BroadcastReceiver receiver;
public void createReceiver(BroadcastReceiver receiver){
this.receiver = receiver;
}
}
ReceiverManager
的createReceiver
的参数是BroadcastReceiver
,在ReceiverManager的子类OnePixelReceiverManager 中调用createReceiver时,用OnePixelReceiver
实例化了BroadcastReceiver
,这符合里氏代换原则
,其定义如下:
里氏代换原则
:所有引用基类的地方必须能透明地使用其子类的对象。
在里氏代换原则中,应该将父类设计为抽象类或者接口,让子类继承父类或实现父接口,并实现在父类中声明方法,在运行时子类实例替换父类实例。更详细可参考【设计模式】里氏代换原则
设计ActivityManager和ReceiverManager是为了让代码符合开闭原则
,因为这两个管理类中都提取了Activity和Receiver的共性方法,如果需要增加其它具体的Activity和Receiver管理类,只需创建一个新的具体类,而不需要修改ActivityManager和ReceiverManager代码,符合开闭原则
,开闭原则定义如下:
开闭原则
: 软件实体应该对扩展开放,对修改关闭。
设计Manager接口也是如此,该接口是预留接口,后续可能会用到。
2.6 再看看OnePixelActivity里修改部分
package com.yds.jianshu.onepixel;
import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.Gravity;
import android.view.Window;
import android.view.WindowManager;
import com.yds.jianshu.manager.OnePixelActivityManager;
public class OnePixelActivity extends Activity{
private static final String TAG = "[OnePixelActivity]";
private OnePixelActivityManager manager;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setWindowAttributes();
initData();
Log.e(TAG,"onCreate");
}
private void initData(){
manager = new OnePixelActivityManager();
manager.registerActivityReference(this);//将引用传给OnePixelActivityManager
}
private void setWindowAttributes(){
Window window = getWindow();
window.setGravity(Gravity.LEFT|Gravity.TOP);
WindowManager.LayoutParams params = window.getAttributes();
params.x = 0;
params.y = 0;
params.height = 1;
params.width = 1;
window.setAttributes(params);
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.e(TAG,"onDestroy");
}
@Override
protected void onStop() {
super.onStop();
Log.e(TAG,"onStop");
}
@Override
protected void onPause() {
super.onPause();
Log.e(TAG,"onPause");
}
@Override
protected void onStart() {
super.onStart();
Log.e(TAG,"onStart");
}
@Override
protected void onResume() {
super.onResume();
Log.e(TAG,"onResume");
}
}
2.7 OnePixelReceiver源码
package com.yds.jianshu.onepixel;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import com.yds.jianshu.manager.OnePixelActivityManager;
public class OnePixelReceiver extends BroadcastReceiver {
private static final String TAG = "[OnePixelReceiver]";
private OnePixelActivityManager manager;
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
manager = new OnePixelActivityManager();
if (Intent.ACTION_SCREEN_ON.equals(action)){//如果亮屏,则关闭1像素Activity
manager.finishOnePixelActivity();
}else if(Intent.ACTION_SCREEN_OFF.equals(action)){//如果息屏,则开启1像素Activity
manager.startActivity(context);
}
}
}
2.8 OnePixelService源码部分
package com.yds.jianshu.onepixel;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import com.yds.jianshu.manager.OnePixelReceiverManager;
import com.yds.jianshu.manager.ReceiverManager;
public class OnePixelService extends Service {
private ReceiverManager manager;
public OnePixelService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
manager = new OnePixelReceiverManager();//符合里氏代换原则
manager.register(this);//注册广播接收者
return START_STICKY;
}
@Override
public void onDestroy() {
manager.unregister(this);
}
}
在上述代码中,使用了OnePixelReceiverManager来实例化ReceiverManager ,符合里氏代换原则
。
2.9 MainActivity代码
package com.yds.jianshu.mobile;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import com.example.myapplication.R;
import com.yds.jianshu.onepixel.OnePixelService;
public class MainActivity extends AppCompatActivity{
private static final String TAG = "[MainActivity]";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
}
private void initData(){
startOnePixelService();
}
private void startOnePixelService(){
Intent intent = new Intent();
intent.setClass(MainActivity.this, OnePixelService.class);
startService(intent);
}
@Override
protected void onDestroy() {
super.onDestroy();
}
}
该部分代码基本不变。
在此基础上,还增加了一个工具类,用于对对象判空
package com.yds.jianshu.utils;
/**
* Created by yds
* on 2019/8/2.
*/
public class ObjectUtil {
public static T requireNonNull(T object,String message){
if(object == null){
throw new NullPointerException(message);
}
return object;
}
}
3 重构后的UML图
暂时不提供
4 相关文章
【Android实例】1像素进程保活(一)
【Android实例】1像素进程保活(二)
【设计模式】单一职责原则
【设计模式】开闭原则
【设计模式】里氏替换原则