2020 Android 大厂面试(六)架构设计和设计模式

3,963 阅读11分钟

六、架构设计和设计模式

1.谈谈你对Android设计模式的理解
2.MVC MVP MVVM原理和区别
3.你所知道的设计模式有哪些?
4.项目中常用的设计模式
5.手写生产者/消费者模式
6.写出观察者模式的代码
7.适配器模式,装饰者模式,外观模式的异同?
8.用到的一些开源框架,介绍一个看过源码的,内部实现过程。
9.谈谈对RxJava的理解
10.Rxjava发送事件步骤
11.RxJava的作用,与平时使用的异步操作来比的优缺点
12.说说EventBus作用,实现方式,代替EventBus的方式
13.从0设计一款App整体架构,如何去做?
14.说一款你认为当前比较火的应用并设计(比如:直播APP,P2P金融,小视频等)
15.谈谈对java状态机理解
16.Fragment如果在Adapter中使用应该如何解耦?
17.Binder机制及底层实现
18.对于应用更新这块是如何做的?(解答:灰度,强制更新,分区域更新)?
19.实现一个Json解析器(可以通过正则提高速度)
20.统计启动时长,标准

参考答案:

1.谈谈你对Android设计模式的理解

blog.csdn.net/github_3713…

www.jianshu.com/p/1a9f571ad…

六大原则

单一职责 一人做一事
开闭原则 对扩展开放 对修改封闭
里式替换 继承和多态的体现 父类声明 子类new
依赖倒置 解耦 高层依赖接口 不依赖细节
接口隔离 最小接口 7 + 2
迪米特   最少了解

设计模式

单例模式

public class Singleton {

    private volatile static Singleton instance;
    
    //将默认的构造函数私有化,防止其他类手动new
    private Singleton() {
    }
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

Builder模式

 AlertDialog.Builer builder = new AlertDialog.Builder(context);
 builder.setIcon(R.drawable.icon)
         .setTitle("title")
         .setMessage("message")
         .setPositiveButton("Button1",
                 new DialogInterface.OnclickListener() {
                     public void onClick(DialogInterface dialog, int whichButton) {
                         setTitle("click");
                     }
                 })
         .create()
         .show();

原型模式

Uri uri = Uri.parse("smsto:10086");
Intent shareIntent = new Intent(Intent.ACTION_SENDTO, uri);
//克隆副本
Intent intent = (Intetn) shareIntent.clone();
startActivity(intent);

工厂模式


public Object getSystemService(String name) {
    if (getBaseContext() == null) {
        throw new IllegalStateException("System services not available to Activities before onCreate()");
    }
    //........
    if (WINDOW_SERVICE.equals(name)) {
         return mWindowManager;
    } else if (SEARCH_SERVICE.equals(name)) {
        ensureSearchManager();
        return mSearchManager;
    }
    //.......
    return super.getSystemService(name);
  }

抽象工厂

 public class BaseService extends Service{
    @Nullable
    @Override
    public IBinder onBind(Intent intent){
        return new Binder();
    }
    
}

策略模式

状态模式

WIFI

责任链模式

android 点击

解释器模式

PackageManagerService 解释 Manifest

命令模式

观察者模式

ListView notifyDataSetChanged()

备忘录模式

onSaveInstanceState
onRestoreInstanceState

迭代器模式

Iterator
Cursor
cursor.moveToFirst();
do{
    //cursor.getXXX(int);
} while (cursor.moveToNext);

模板方法模式

Activity

访问者模式

APT Annotation Processing Tools

中介者模式

中介者对象是将系统从网状结构转为以调停者为中心的星型结构。

ServiceManager持有各种系统服务的引用 ,当我们需要获取系统的Service时,比如ActivityManager、WindowManager等(它们都是Binder),
首先是向ServiceManager查询指定标示符对应的Binder,再由ServiceManager返回Binder的引用。
这里的ServiceManager和Binder驱动就是中介者。

代理模式

aidl

组合模式

ViewGroup

适配器模式

ListView RecyclerView

装饰模式

Context

ContextThremeWrapper 继承 ContextWrapper 继承 Context
ContextWrapper 持有 mBase(ContextImpl)

享元模式

Message.obtain()

外观模式

Context

桥接模式

View Display HardwareLayer Canvas

MVC MVP MVVM

M 数据库/网络 -> V
V 布局 Activity Fragment -> M C
C Activity Fragment -> M V

M 数据库/网络 -> P
V 布局 Activity Fragment -> P
P Presenter -> M V

M 数据库/网络 -> VM
V 布局 Activity Fragment -> VM
VM ViewModel -> M

2.MVC MVP MVVM原理和区别

www.jianshu.com/p/5e94569a4…

3.你所知道的设计模式有哪些?

juejin.cn/post/684490…

继承 实现 组合 聚合 关联 依赖

简单工厂 Simpale Factory Pattern

工厂根据参数创建不同的产品,产品都实现同一接口。一个工厂,多个产品

工厂方法模式 Factory Method Pattern

各自的工厂生产各自的一个产品,工厂、产品都实现于抽象类。多个工厂,多个产品

抽象工厂模式 Abstract Factory Pattern

各自的工厂生产各自的一组产品,工厂、产品都实现于抽象类。多个工厂,多组产品

单例模式 Singleton Pattern

/**
 * Singleton helper class for lazily initialization.
 *
 * Modeled after frameworks/base/include/utils/Singleton.h
 *
 * @hide
 */
public abstract class Singleton<T> {
    @UnsupportedAppUsage
    public Singleton() {
    }
    @UnsupportedAppUsage
    private T mInstance;
    protected abstract T create();
    @UnsupportedAppUsage
    public final T get() {
        synchronized (this) {
            if (mInstance == null) {
                mInstance = create();
            }
            return mInstance;
        }
    }
}

生成器模式 建造者模式 Builder Pattern

复杂对象构建分步进行,相同步骤不同表示

原型模式 Prototype Pattern

Linux Zygote 进程

装饰模式 Decorator Pattern

不改变原有对象,动态增加格外功能 ContextImpl

外观模式 Facade Pattern

同一对外定义简单接口

代理模式 Proxy Pattern

在原访问路径中增加一个代理

享元模式 Flyweight Pattern

桥接模式 Bridge Pattern

将抽象部分与他的实现部分分开,使他们都能独立的变化

适配器模式 包装器 Adapter Pattern Wrapper Pattern

责任链模式 Chain of Responsibility Pattern

避免耦合,层层传递,触摸事件传递

命令模式 Command Pattern

请求封装为命令

解释器模式 Interpreter Pattern

定义语法,建立解释器

迭代器模式 Iterator Pattern

统一迭代方式

中介者模式 Madiator Pattern

解耦

备忘录模式 Memento Pattern Token Pattern

对象之外保存一个对象状态,用于后期恢复

onSaveInstanceState

onRestoreInstanceState

观察者模式 Observer Pattern

多人订阅一个新闻频道

发布-订阅(Publish/Subscribe)模式
模型-视图(Model/View)模式
源-监听器(Source/Listener)模式
从属者(Dependents)模式

状态模式 State Pattern

一定一组状态,每个状态可以相互替换,非独立存在

策略模式 Strategy Pattern Policy Pattern

定义一组策略,每个策略可以相互替换,并且独立存在

模板方法模式 Template Method

定义操作,子类实现

访问者模式 Visitor Pattern

4.项目中常用的设计模式

www.jianshu.com/p/61b67ca75…

创建型模式:单例模式、抽象工厂模式、建造者模式、工厂模式、原型模式。
结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。
行为型模式:模版方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式(责任链模式)、访问者模式。

5.手写生产者/消费者模式

juejin.cn/post/684490…

6.写出观察者模式的代码

blog.csdn.net/u013390476/…

7.适配器模式,装饰者模式,外观模式的异同?

blog.csdn.net/hp910315/ar…

共同点:介于调用者和被调者之间,中间层,起到隔离

不同点:装饰模式是“新增行为”,代理模式是“控制访问行为”,适配器模式是"转换行为",外观模式是一种"简化行为"

适配器模式:包装另一个对象,并提供不同的接口。
外观模式:包装许多对象,以简化他们的接口。
装饰者模式:包装另一个对象,并提供额外的行为。
代理模式:包装另一个对象,并控制对它的访问。

8.用到的一些开源框架,介绍一个看过源码的,内部实现过程。

9.谈谈对RxJava的理解

kknews.cc/code/yv9k2p…

//被观察者 
Observable novel = Observable.create(new ObservableOnSubscribe<String>() {
    @Override
    public void subscribe(ObservableEmitter<String> emitter) throws Exception {
        emitter.onNext("连载1");
        emitter.onNext("连载2");
        emitter.onNext("连载3");
        emitter.onComplete();
    }
});

回调细节:

onNext方法可以无限调用,所有的调用都能接收到,
onComplete 可重复调用,只接受一次,与 onError 互斥
onError 只能调用一次,第二次会报异常,与 onComplete 互斥

代码:

Observable.create(new ObservableOnSubscribe<String>() {
    @Override
    public void subscribe(ObservableEmitter<String> emitter) throws Exception {
        emitter.onNext("连载1");
        emitter.onNext("连载2");
        emitter.onNext("连载3");
        emitter.onComplete();
    }
}).observeOn(AndroidSchedulers.mainThread())//回调在主线程 
    .subscribeOn(Schedulers.io())//执行在io线程
    .subscribe(new Observer<String>() {
        @Override
        public void onSubscribe(Disposable d) {
            Log.e(TAG, "onSubscribe");
        }

        @Override
        public void onNext(String value) {
            Log.e(TAG, "onNext:" + value);
        }

        @Override
        public void onError(Throwable e) {
            Log.e(TAG, "onError=" + e.getMessage());
        }

        @Override
        public void onComplete() {
            Log.e(TAG, "onComplete()");
        }
    });

复杂操作

Observable.create(new ObservableOnSubscribe<Drawable>() {
     @Override
     public void subscribe(ObservableEmitter<Drawable> emitter) throws Exception {
         for (int i = 0; i < drawableRes.length; i++) {
             Drawable drawable = getResources().getDrawable(drawableRes[i]);
             //第6个图片延时3秒后架子
             if (i == 5) {
                 sleep(3000);
             }
             //复制第7张图片到sd卡 
             if (i == 6) {
                 Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
                 saveBitmap(bitmap, "test.png", Bitmap.CompressFormat.PNG);
             }
             //第8张上传到网络
             if (i == 7) {
                 updateIcon(drawable);
             }
             emitter.onNext(drawable);
         }
     }
 }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<Drawable>() {
     @Override
     public void accept(Drawable drawable) throws Exception {
         //回调后在UI界面上展示出来
     }
 });

10.Rxjava发送事件步骤

www.jianshu.com/p/8ac4ae875…

注: 比如发送多个onComplete是可以正常运行的, 依然是收到第一个onComplete就不再接收了, 但若是发送多个onError, 则收到第二个onError事件会导致程序会崩溃.
注意: 调用dispose()并不会导致上游不再继续发送事件, 上游会继续发送剩余的事件.

www.jianshu.com/p/10f5250ba…

map
flatmap 不保证顺序
concatmap 保证顺序

Flowable的源码中就有这个buffersize 128 MissingBackpressureException

11.RxJava的作用,与平时使用的异步操作来比的优缺点

blog.csdn.net/github_3713…

又叫响应式编程、响应式扩展ReactiveX 是基于观察者模式设计的,核心对象只有 Observable 和 Observer。

Rx使代码简化

函数式风格:对可观察数据流使用无副作用的输入输出函数,避免了程序里错综复杂的状态
简化代码:Rx的操作符通通常可以将复杂的难题简化为很少的几行代码
异步错误处理:传统的try/catch没办法处理异步计算,Rx提供了合适的错误处理机制
轻松使用并发:Rx的Observables和Schedulers让开发者可以摆脱底层的线程同步和各种并发问题

RxJava 的优势也是简洁,但它的简洁的与众不同之处在于,随着程序逻辑变得越来越复杂,它依然能够保持简洁

12.说说EventBus作用,实现方式,代替EventBus的方式

blog.csdn.net/github_3713…

13.从0设计一款App整体架构,如何去做?

blog.csdn.net/github_3713…

想要设计App的整体框架,首先要清楚我们做的是什么

一般我们与网络交互数据的方式有两种:主动请求(http),长连接推送

结合网络交互数据的方式来说一下我们开发的App的类型和特点:

数据展示类型的App:特点是页面多,需要频繁调用后端接口进行数据交互,以http请求为主;推送模块,IM类型App的IM核心功能以长连接为主,比较看重电量、流量消耗。

手机助手类App:主要着眼于系统API的调用,达到辅助管理系统的目的,网络调用的方式以http为主。

游戏:一般分为游戏引擎和业务逻辑,业务脚本化编写,网络以长连接为主,http为辅。
一般我们做的App都是类型1,简要来说这类app的主要工作就是

把服务端的数据拉下来给用户展示 把用户在客户端修改的数据上传给服务端处理 所以这类App的网络调用相当频繁,而且需要考虑到网络差,没网络等情况下,App的运行,成熟的商业应用的网络调用一般是如下流程:

UI发起请求 - 检查缓存 - 调用网络模块 - 解析返回JSON / 统一处理异常 - JSON对象映射为Java对象 - 缓存 - UI获取数据并展示

这之中可以看到很明显职责划分,即:数据获取;数据管理;数据展示

14.说一款你认为当前比较火的应用并设计(比如:直播APP,P2P金融,小视频等)

juejin.cn/post/684490…

blog.csdn.net/xJ032w2j4cC…

15.谈谈对java状态机理解

blog.csdn.net/github_3713…

有限状态机

状态 条件 时间 动作 迁移

分层状态机

16.Fragment如果在Adapter中使用应该如何解耦?

blog.csdn.net/hitgaoxing/…

MVVM

17.Binder机制及底层实现

blog.csdn.net/github_3713…

18.对于应用更新这块是如何做的?(解答:灰度,强制更新,分区域更新)?

www.qingtingip.com/h_239744.ht…

19.实现一个Json解析器(可以通过正则提高速度)

blog.csdn.net/Dome_/artic…

20.统计启动时长,标准

blog.csdn.net/github_3713…

adb shell am start -w packagename/activity

WaitTime 返回从 startActivity 到应用第一帧完全显示这段时间. 就是总的耗时,包括前一个应用 Activity pause 的时间和新应用启动的时间;

ThisTime 表示一连串启动 Activity 的最后一个 Activity 的启动耗时;

TotalTime 表示新应用启动的耗时,包括新进程的启动和 Activity 的启动,但不包括前一个应用Activity pause的耗时。

生命周期函数执行流程

-> Application 构造函数
-> Application.attachBaseContext()
-> Application.onCreate()
-> Activity 构造函数
-> Activity.setTheme()
-> Activity.onCreate()
-> Activity.onStart
-> Activity.onResume
-> Activity.onAttachedToWindow
-> Activity.onWindowFocusChanged

1.起始时间点

 Application.attachBaseContext() 
 Activity.onRestart()

2.结束时间点

Activity.onResume 错误
Activity.onWindowFocusChanged