第三天(組件化,插件化,模塊化是什麼,有什麼區別)

組件化與插件化相同之處: 是將一個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資源文件不能重複

 

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