Android架构

MVC

mvc model view controller 模式视图控制器

  • M: 业务逻辑处理
  • V:处理数据显示的部分
  • C:Activity处理用户交互的问题,中间桥梁的作用,解耦的作用。

特点:

  • 耦合性低
  • 扩展性好,利于维护
  • 模块职责划分明确

Model层:

//状态的回调
    public interface LoginResultListener {
    void result(boolean status);
}
    
//接口
    public interface UserModel {

    public void login(String name, String password, LoginResultListener listener);

}
    //实现类,进行具体的业务操作
    public class UserModelImp implements UserModel {

    @Override
    public void login(String name, String password, LoginResultListener listener) {
        //todo进行相关的操作
    }
}

view层:

<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="rao.com.mvc.MvcDemoActivity">

    <android.support.design.widget.TextInputLayout
        android:id="@+id/til_username"
        android:layout_width="368dp"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:hint="用户名"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <android.support.design.widget.TextInputEditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            />
    </android.support.design.widget.TextInputLayout>

    <android.support.design.widget.TextInputLayout
        android:id="@+id/til_password"
        android:layout_width="368dp"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/til_username">

        <android.support.design.widget.TextInputEditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="密码"/>
    </android.support.design.widget.TextInputLayout>

    <Button
        android:id="@+id/bt_login"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:text="login"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/til_password"/>
</android.support.constraint.ConstraintLayout>

controller:

    public class MvcDemoActivity extends AppCompatActivity {

    private TextInputLayout mTilUserName;
    private TextInputLayout mTilPassword;
    private Button mBtLogin;
    private UserModelImp mUserModelImp;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_mvc_demo);
        mTilUserName = findViewById(R.id.til_username);
        mTilPassword = findViewById(R.id.til_password);
        mBtLogin = findViewById(R.id.bt_login);
        mUserModelImp = new UserModelImp();

        mBtLogin.setOnClickListener(view -> {
            mUserModelImp.login(mTilUserName.getEditText().getText().toString(), mTilPassword.getEditText().getText().toString(), new LoginResultListener() {
                @Override
                public void result(boolean status) {
                
                }
            });
        });

    }
}

在实际的使用过程中xml布局起的作用是十分的有限的,同时Activty需要操作ui和业务逻辑,造成冗余。

MVP

M:依然是业务逻辑和实体类型模型
V:对应于Activity,负责View的绘制以及与用户交互
P:负责完成View于Model间的交互。

mvp和mvc.png

定义model层:

    //接口回调
    public interface OnLoginListener {
    void onLoginResult(int status, User user);
}
//定义业务
    public interface IUserBiz {
    void login(String username, String password, OnLoginListener listener);
}
//具体的实现类
    public class UserBiz implements IUserBiz {
    @Override
    public void login(String username, String password, OnLoginListener listener) {
        // TODO: 2018/3/18 ,进行登录,网络数据等操作
        boolean status = true;
        if (status) {
            listener.onLoginResult(1, new User(username, password));
        } else {
            listener.onLoginResult(0, null);
        }
    }
}

view层:

    //view相关
    public interface IUserLoginView {
    String getUsername();

    String getPassword();

    void showLoading();

    void dismissLoading();

    void loginStatus(int status);
}

//activity
public class MVPActivity extends AppCompatActivity implements IUserLoginView {
    private TextInputLayout mTilUserName;
    private TextInputLayout mTilPassword;
    private Button mBtLogin;
    private ProgressDialog mProgressDialog;
    private UserLoginPresenter mUserLoginPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_mvp);
        mTilUserName = findViewById(R.id.til_username);
        mTilPassword = findViewById(R.id.til_password);
        mBtLogin = findViewById(R.id.bt_login);
        mProgressDialog = new ProgressDialog(this);
        mUserLoginPresenter = new UserLoginPresenter(this);

        mBtLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mUserLoginPresenter.login();
            }
        });
    }

    @Override
    public String getUsername() {
        return mTilUserName.getEditText().getText().toString();
    }

    @Override
    public String getPassword() {
        return mTilPassword.getEditText().getText().toString();
    }

    @Override
    public void showLoading() {
        mProgressDialog.show();
    }

    @Override
    public void dismissLoading() {
        mProgressDialog.dismiss();
    }

    @Override
    public void loginStatus(int status) {
        //todo,根据操作,去进行响应的跳转
    }
}

presenter层:

    public class UserLoginPresenter {
    private IUserBiz mIUserBiz;
    private IUserLoginView mIUserLoginView;

    public UserLoginPresenter(IUserLoginView IUserLoginView) {
        mIUserLoginView = IUserLoginView;
        mIUserBiz = new UserBiz();
    }

    public void login() {
        mIUserLoginView.showLoading();
        mIUserBiz.login(mIUserLoginView.getUsername(), mIUserLoginView.getPassword(), new OnLoginListener() {
            @Override
            public void onLoginResult(int status, User user) {
                if (status == 1) {
                    mIUserLoginView.loginStatus(1);
                } else {
                    mIUserLoginView.loginStatus(0);
                }
            }
        });
    }
}

MVVM

View: 对应于Activity和xml,负责View的绘制,以及用户交互。
Model:实体模型,数据存取
ViewModel:负责完成View与Model间的交互,负责业务逻辑。
一把配套使用DataBinding使用,Model与ViewModel双向通信,一般使用数据驱动的方式来实现。view只负责UI操作。

mvvm.png

Android插件化

  • 当业务量大的时候,android的65536方法数的限制。
  • apk大的时候,动态加载apk:一个宿主的apk,到sd卡中动态的加载apk,
  • 资源加载:通过AssertManagerr类
  • 代码加载 :java中类加载机制

动态加载APk:类加载器,就是将java的字节码加载到虚拟机当中android中有两个重要的

  • DexClassLoader: 可以从dex文件加载字节码文件,用于动态加载和热更新等。
  • PathClassLoader:只能加载文件目录下的apk

资源加载:AssertManager反射来加载的
代码加载:反射绑定到activity的生命期,之后在加载

Android热更新

  • 线上检测到严重的 crash
  • 拉出bugfix分支并在分支上修复问题
  • jenkins构建和补丁生成
  • app推送或主动拉取文件
  • 将bugfix代码合并到master上

热更新框架:

  • Dexposed :阿里,基于aop的思想,无需重启,即可修复,通过hook技术,不仅可以修改java方法,还能hook修改android方法,日志记录,性能统计,安全控制,事物处理。(hook基本的方法就是通过hook“接触”到需要修改的api函数入口点,改变它的地址指向新的自定义的函数)
  • AndFix:阿里,更纯粹的热修护技术,性能较好,工具较完善。
  • Nuwa:基于dex分包的技术,将dex文件拆分多个dex,编上号,依次加载。

原理:

  • Android类加载机制
    • PathClassLoader 加载系统的类,应用类
    • DexClassLoader 加载Dex文件,apk包
  • 热修复机制
    • dexElements 会创建dex数组
    • ClassLoader 会遍历这个数据,根据线上的carch定位到这个dex,将修复好的dex的位置靠前,优先加载这个dex文件。

进程保活

使用场景:定位,推送等等

进程优先级:

  • 前台进程
  • 可见进程(没有前台组件,但是会影响前台界面的进程)
  • 服务进程
  • 后台进程
  • 空进程(缓存)

回收策略:

  • low memory killer:通过一系列的评分机制,定义进程进行打分,将分数搞的进程判定为bad进程,杀死并释放缓存。(定时检查)
  • OOM_ODJ:这个阀值,判断进程的优先级,越大进程优先级越低。

保活方案:

  • 系统广播拉活,开机,网络数据变化,不可控制(容易被系统软件禁用)
  • 系统Service机制拉活 :利用的是当系统内存不足而杀掉该Service,可以拉活。杀死Service后,第一5秒拉活,二次10秒后拉活,三次20秒拉活,当Serice被系统拉活三次之后,就不会在被系统进行拉活了。当被安全软件或系统软件静止之后,是不能拉活的。
  • 利用native进程拉活:利用linux的fork机制创建一个进程,监控主进程的存活,这是可以立即对主进程进行拉活。(失效了)
  • JobScheduler机制拉活,跟native类是,android5.0之后提供的。
  • 帐号同步机制拉活 (不再生效)

UIL

Universe Image Loader图片加载框架

Lint检查

Android Lint是一个静态的代码分析工具,它能够对android项目潜在的bug,可优化的代码,安全性,性能,可用性,可访问性国际化等进行检查。

Lint工作流程:通过配置lint.xml配置,运用lintTool工具,进行相关的额检查
在Src文件目录下,创建lint.xml文件

Lint.png
<?xml version="1.0" encoding="utf-8"?>
<lint>
    <!--因为 lint误报,必须负略它-->
    <issue id="MissingRegistered" severity="ignore"/>
    <!--选择性负略 begain-->
    <issue id="OnClick" severity="ignore"/>
    <issue id="StringFormatInvalid">
        <ignore path="res/"/>
    </issue>
    <issue id="Orientation" severity="ignore"/>
    <issue id="NewApi">
        <ignore path="res/"/>
    </issue>
    <!--选择性忽略 end-->

    <!--忽略一些不必要的警告-->
    <!--忽略对right-to-left布局的支持-->
    <issue id="RtlHardcoded" severity="ignore"/>
    <issue id="RtlSymmetry" severity="ignore"/>

    <!--忽略ImageView的ContentDescription-->
    <issue id="ContentDescription" severity="ignore"/>
</lint>

如果确定java代码写的没有问题,你可以以下的方式使用

//在java代码中的使用,忽略这警告,检查,这是在lint.xml中配置了属性的   
@SuppressLint("NewApi")
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    initView(savedInstanceState);
}

//在xml文件中的使用,当代码执行到这里的时候就会忽略未使用的资源的问题,不会对编译尽心检查
tools:ingnore="UnusedResources"

自定义lint
使用默认的lint检查不能满足需求,在自定义库的使用,某些属性没有配置 BuiltinlssueRegistry

Kotlin

  • Kotlin一种基于JVM的编程语言
  • 是对java的一种扩展
  • Kotlin支持函数式编程
  • Kotlin类与Java类互相调用
  • 定位carch定位的堆栈的问题

安装Kotlin 插件 在android studio安装

推荐阅读更多精彩内容