android 代码设置像素,【Android实例】用设计原则来重构1像素保活代码

1 类图

在【FJU项目】1像素进程保活(二)中,涉及到的几个类的类图如下所示(仅供参考):

实线箭头:关联

虚线箭头:依赖

98b30c2254b5

重构前UML类图在上图中,OnePixelManager里面有太多的职责,违背了单一职责原则。里面还有很多地方违背了其它的设计原则,稍后通过代码进行分析。

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 相关文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值