第三天(组件化,插件化,模块化是什么,有什么区别)

组件化与插件化相同之处: 是将一个APP拆分为多个模块去开发.

插件化: 如果我们把一个APP分为多个模块来开发的化,我们最终打包的时候永远只需要打包当前的主apk就可以,其它的功能模块可以不管,它们可以当作是一个独立的apk来单独运行,甚至单独发布,单独给用户用.当我们项目达到一定体积时,一般都会用插件化开发

不仅仅是apk也可以是libralaly(dex)

好处: 1,提高编译速度,节省开发时间.

          2,业务模块解藕,便于后期维护.

          3,团队开发便利.

          4,动态更新插件,按需下载模块.

 

原理: 当我们点击相应的模块时,就会从服务器下载相应的插件APK或者Library,存放到本地指定目录下, 下载完之后我们就会去动态加载这个apk里面的 资源对象(我们需要在apk里面用到这些资源) 以及 类加载器(第三方插件apk是不具备生命周期以及没有上下文),通过插件apk的类加载器获取到插件化apk中的Activity的类对象,然后进行跳转.

主要涉及到的类有:

DexClassLoader:加载第三方插件apk的类加载器
Context:APP的上下文
PackageInfo:插件apk的包信息类,因为我们需要根据包信息名字获取Activity的名字
Resources:加载第三方插件apk的资源对象

 代码好下:

File fileDir = mContext.getDir("odex", Context.MODE_PRIVATE);
//只有一个classloader   optimizedDire:当前应用的私有存储路径
mClassLoader = new DexClassLoader(path, fileDir.getAbsolutePath(), null, mContext.getClassLoader());
//获取到包管理器(packageManager) 整个系统有只有一个
PackageManager packageManager = mContext.getPackageManager();
//通过包管理器获取到传进来的这个路径下的dex文件下的包信息类
mPackageInfo = packageManager.getPackageArchiveInfo(path, PackageManager.GET_ACTIVITIES);
try {
    AssetManager assetManager = AssetManager.class.newInstance();
    //反射获取方法
    Method addAssetPath = assetManager.getClass().getMethod("addAssetPath", String.class);
    addAssetPath.invoke(assetManager, path);
    mResources = new Resources(assetManager, mContext.getResources().getDisplayMetrics(), mContext.getResources().getConfiguration());
} catch (Exception e) {
    e.printStackTrace();
}

因为是加载第三方插件apk,而第三方插件apk是没有生命周期的,所以我们需要帮其注入生命周期,这时就需要一个代码的Activity我们这命名为ProxyActiviy ,所有的绑定生命周期的逻辑都是在ProxyActiviy操作.

核心代码如下:

private PluginInterface mPluginInterface;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //获取到真正的目的地的Activity的名字
    String activityName = getIntent().getStringExtra("activityName");
    try {
        Class<?> aClass = PluginManager.getInstance().getClassLoader().loadClass(activityName);
        //实例化插件化中的Activity
        Object activity = aClass.newInstance();
        //判断这个对象是否按照我们的标准来
        if (activity instanceof PluginInterface) {
            mPluginInterface = (PluginInterface) activity;
            Bundle bundle = new Bundle();
            mPluginInterface.attach(this);
            mPluginInterface.onCreate(bundle);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

从上面代码可以看出,我们创建了一个第三方插件里面的Activity类,然后将执行其attacth,和onCreate也就是将代码Activity的一下文传进去,然后再执行其的onCreate,就是把第三方插件里面的Activity当作一个普通的类来使用,我们再来看一个第三方Activity里的代码

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login);
    mTextView = findViewById(R.id.taskview);
    Button button = findViewById(R.id.btn);
    mTextView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(mActivity, "我开始要工作了", Toast.LENGTH_SHORT).show();
            Intent intent = new Intent(mActivity, SecendActivity.class);
            startActivity(intent);
        }
    });
    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            setting(v);
        }
    });
}

再把BaseActivit代码贴出来

public class BaseActivity extends AppCompatActivity implements PluginInterface {

    protected Activity mActivity;

    @Override
    public void attach(Activity alipayActivity) {
        mActivity = alipayActivity;
    }

    public void setContentView(View view) {
        if (mActivity == null) {
            super.setContentView(view);
        } else {
            mActivity.setContentView(view);
        }
    }

    @Override
    public void setContentView(int layoutResID) {
        mActivity.setContentView(layoutResID);
    }

    @Override
    public Intent getIntent() {
        return mActivity.getIntent();
    }

    @Override
    public ClassLoader getClassLoader() {
        return mActivity.getClassLoader();
    }

    @Override
    public <T extends View> T findViewById(int id) {
        return mActivity.findViewById(id);
    }

    @NonNull
    @Override
    public LayoutInflater getLayoutInflater() {
        return mActivity.getLayoutInflater();
    }

    @Override
    public void startActivity(Intent intent) {
        Intent m = new Intent();
        m.putExtra("activityName", intent.getComponent().getClassName());
        mActivity.startActivity(m);
    }

    @Override
    public ApplicationInfo getApplicationInfo() {
        return mActivity.getApplicationInfo();
    }

    @Override
    public Window getWindow() {
        return mActivity.getWindow();
    }

    @Override
    public WindowManager getWindowManager() {
        return mActivity.getWindowManager();
    }

    @SuppressLint("MissingSuperCall")
    @Override
    public void onCreate(Bundle savedInstanceState) {

    }

    @SuppressLint("MissingSuperCall")
    @Override
    public void onStart() {

    }

    @SuppressLint("MissingSuperCall")
    @Override
    public void onResume() {

    }

    @SuppressLint("MissingSuperCall")
    @Override
    public void onPause() {

    }

    @SuppressLint("MissingSuperCall")
    @Override
    public void onStop() {

    }

    @Override
    public void onDestory() {

    }

    @SuppressLint("MissingSuperCall")
    @Override
    public void onSaveInstanceState(Bundle outState) {

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return false;
    }

    @Override
    public void onBackPressed() {
    }
}

从上面二大段代码可以得出,在第三方Actitivy里面里的setContentView,其实调用的就是代码类ProxyActivity执行setConttentView,里面所有涉及到的操作上下文的操作都是代码类来完成的.

组件化:将一个app分为多个模块开发之后,最终还是会打包成一个apk.解决不了包大小问题(按照功能模块单独开发)

为什么选择组件化:    1,单一模块不行于团队开发  

                                   2,单一模块对项目任一修改都要编译整个工程 

                                   3,单一模块功能复用不是很强(比如一个登陆,多个APP都可以用,整个模块移走)

                                   4,单一模块之间业务耦合非常严重

组件化解决的问题:    1,提高编译速度,节省开发时间 

                                   2,业务模块解耦,便于后期维护 

                                   3,团队开发方便

                                   4 使得功能复用更简单

组件化框架注意点:    1,类名and资源文件不能重复

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章