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安装

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,335评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,895评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,766评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,918评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,042评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,169评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,219评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,976评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,393评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,711评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,876评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,562评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,193评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,903评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,142评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,699评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,764评论 2 351

推荐阅读更多精彩内容