美文网首页热修复
AndFix组件化封装

AndFix组件化封装

作者: 小楠总 | 来源:发表于2017-11-30 10:05 被阅读178次

前言

为了防止框架的引入对自身项目代码的入侵,我们有必要对引入的框架利用组件化的思想进行一次封装。除了防止代码入侵以外,同时也简化了使用,实现了项目的需求。

原理

正所谓开具一张图,内容全靠写,先来看一下封装之后代码的整体流程:

AndFix组件化封装.png

主要的核心思想是:

  1. 创建一个后台的FixService
  2. 在进入APP的时候(闪屏页)启动
  3. 然后请求服务器,服务器返回是否有Patch
  4. 如果有Patch,就进行下载、Fix;如果没有Patch,就结束FixService

封装过程

为了防止代码入侵、简化使用,我们先来封装一个FixManager,专门用来管理热修复相关的逻辑。有了FixManager,以后替换框架的时候,也不会影响项目的其他代码了。

下面来看看FixManager的代码:

public class FixManager {

    private static FixManager sInstance;
    private PatchManager mPatchManager;

    private FixManager() {}

    public static FixManager getInstance() {
        if (sInstance == null) {
            synchronized (FixManager.class) {
                if (sInstance == null) {
                    sInstance = new FixManager();
                }
            }
        }
        return sInstance;
    }

    public void init(Context context) {
        mPatchManager = new PatchManager(context);
        mPatchManager.init(Utils.getVersionName(context));
        mPatchManager.loadPatch();
    }

    public void addPatch(String path) {
        try {
            mPatchManager.addPatch(path);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

我们通过单例的形式对FixManager进行封装,这是组件化、同时也是外观设计模式的应用。

这里主要提供了init以及addPatch方法,分别用于初始化热修复框架、添加Patch进行热修复。

我们的核心逻辑主要在FixService里面。代码如下:

public class FixService extends Service {

    private static final String TAG = FixService.class.getSimpleName();
    private String mPatchDir;
    private String mPatchFileName;
    private static final String PATCH_FILE_END = ".apatch";

    private static final int MSG_CHECK_UPDATE = 0x01;
    private static final int MSG_DOWNLOAD_PATCH = 0x02;

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_CHECK_UPDATE:
                    checkHasPatch();
                    break;
                case MSG_DOWNLOAD_PATCH:
                    downloadPatch();
                    break;
                default:
                    break;

            }
        }
    };

    private BasePatch mBasePatch;

    @Override
    public IBinder onBind(Intent intent) {
        throw null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        init();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        mHandler.sendEmptyMessage(MSG_CHECK_UPDATE);

        //返回START_STICKY表示服务不会自动重启
        return START_STICKY;
    }

    private void init() {
        mPatchDir = getExternalCacheDir().getAbsolutePath() + "/patch/";
        File patchFile = new File(mPatchDir);
        if (!patchFile.exists()) {
            patchFile.mkdirs();
        }
    }

    private void checkHasPatch() {
        RequestCenter.requestPatchUpdateInfo(new DisposeDataListener() {
            @Override
            public void onSuccess(Object responseObj) {
                mBasePatch = (BasePatch) responseObj;
                if (!TextUtils.isEmpty(mBasePatch.data.downloadUrl)) {
                    Log.e(TAG, "onSuccess: " + "has new patch file");
                    mHandler.sendEmptyMessage(MSG_DOWNLOAD_PATCH);
                } else {
                    stopSelf();
                }
            }

            @Override
            public void onFailure(Object reasonObj) {
                Log.e(TAG, "onFailure: " + "has no patch file");
                stopSelf();
            }
        });
    }

    private void downloadPatch() {
        mPatchFileName = mPatchDir + System.currentTimeMillis() + PATCH_FILE_END;
        Log.e(TAG, "downloadPatch: " + mPatchFileName);
        RequestCenter.downloadFile(mBasePatch.data.downloadUrl, "mPatchFileName", new DisposeDownloadListener() {
            @Override
            public void onProgress(int progress) {
                Log.e(TAG, "onProgress: " + progress + "%");
            }

            @Override
            public void onSuccess(Object responseObj) {
                Log.e(TAG, "onSuccess: " + "正在更新");
                FixManager.getInstance().addPatch(mPatchFileName);
            }

            @Override
            public void onFailure(Object reasonObj) {
                stopSelf();
            }
        });
    }
}

FixService的封装主要是实现了上图的逻辑过程,主要的操作都通过Handler进行统一处理。代码比较简单就不详细介绍了,需要注意的是:在实际开发的时候,需要把网络请求、Bean等代码替换为自己的即可。

在项目中使用

使用上述的封装的时候,需要先在Application中进行初始化:

public class App extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        FixManager.getInstance().init(this);
    }
}

然后,在SplashActivity里面开启FixService,那么Fix逻辑就会在Service中执行了。

public class SplashActivity extends AppCompatActivity {

    private Handler mHandler = new Handler();

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

        Intent fixIntent = new Intent(SplashActivity.this, FixService.class);
        startService(fixIntent);

        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                Intent mainIntent = new Intent(SplashActivity.this, MainActivity.class);
                startActivity(mainIntent);
            }
        }, 2000);
    }
}

AndFix的优劣

最后,我们回过头来聊聊AndFix的优劣:

  1. AndFix的优势是:原理简单、集成简单、使用简单、即时生效
  2. AndFix的不足是:只能修复方法级别的BUG,限制了使用场景,例如不能进行资源、Field等的修改。

相关文章

  • AndFix组件化封装

    前言 为了防止框架的引入对自身项目代码的入侵,我们有必要对引入的框架利用组件化的思想进行一次封装。除了防止代码入侵...

  • iOS开发中的组件化开篇

    什么是组件化? 它是一种App架构思路,对代码进行封装,封装成组件,组件可以单独使用。项目中使用组件包括基础组件(...

  • Android模块化开发实践

    重复造轮子是肯定的 区分概念(组件化,模块化,插件化) 1.组件化封装可重用功能代码,例如网络组件,数据库组件,图...

  • YDL Android 组件化实践与拓展 (1) - 基础功能

    组件化概述 问:什么是组件,什么是组件化? 答:在软件开发领域,组件(Component)是对数据和方法的简单封装...

  • vue大杂烩下(非原创)

    4.组件化 组件:组件就是可被反复使用的,带有特定功能的视图。 所谓的组件化,就像玩积木一样,把封装的组件进行复用...

  • 封装组件

    封装tab组件封装曝光加载组件封装轮播组件 代码

  • 面向对象实战

    封装轮播组件 轮播 封装曝光加载组件 曝光加载 封装Tab 组件 Tab组件

  • ios 制作framework静态库

    新接手的项目要重构,计划往组件化方向搞。提及组件化可能就会涉及到静态库的封装,之前研究过静态库的封装但是那时候没有...

  • 面向对象实战

    1、tab组件封装2、轮播组件封装3、曝光组件封装

  • 组件化和React

    组件化 组件的封装 视图 数据 变化逻辑(数据驱动视图变化) 组件的复用 props传递数据 复用 JSX的本质 ...

网友评论

    本文标题:AndFix组件化封装

    本文链接:https://www.haomeiwen.com/subject/ykkcjxtx.html