浅谈Android设计模式

╄→尐↘猪︶ㄣ 提交于 2020-10-05 00:37:32

浅谈Android设计模式
https://blog.csdn.net/xiaoming100001/article/details/80302143

干货|安卓APP崩溃捕获方案——xCrash

http://blog.itpub.net/69945252/viewspace-2674668/

instance 


//双重检查模式DCL,在某些情况下会失效

if instance == null 

synchronized
  instance == null
  
  /静态内部类单例模式,



SingleDemoHolder 
  instance = SingleDemo
  
  
enum  
INSTANCE ,println 





补充下JVM对内部类的加载顺序

 private static class SingleDemoHolder{
        static {
            System.out.println("调用匿名内部类:Inner Static");
        }
        private static final SingleDemo instance = new SingleDemo(3);



    }


SingleDemo SingleDemoHolder.instance

建造者模式:用来创建复杂对象的模式,将其部件解耦。通常Android中的Dialog或者EventBus使用的时候会碰到。


abstract Builder
abstract void buildCpu
abstract create


extends Builder

computer.setmCpu

buildCpu.buildCpu

buildCpu.create

public abstract class Builder {
    public abstract void buildCpu(String cpu);
    public abstract void buildMainboard(String main_board);
    public abstract void buildGraphicsCard(String graphics_card);
    public abstract void buildRam(String ram);



    public abstract Computer create();
}


/**
 * 真正的建造者,实现build的方法,然后返回组建好的对象
 * Created by XQM on 2018/5/13.
 */
public class BuildComputer extends Builder {
    private Computer computer = new Computer();





    @Override
    public void buildCpu(String cpu) {
        computer.setmCpu(cpu);
    }
OOM  内存泄漏 



AAR 应用程序无响应

、享元模式:是池技术的重要实现方式,可以减少应用程序创建对象,降低产生OOM风险,提高程序的性能。


 享元工厂用来创建具体的享元角色,通过map来缓存对象
 * 如果系统存在大量的相似对象或者缓存池的场景可以使用

GoodsFactory 享元工厂
map 
    private static Map<String,Goods> goodsMap = new HashMap<>();

策略模式:定义一系列的算法,把算法封装起来,并且是它们可以相互替换,使得算法可以独立于使用它的客户而独立变化。比如代码有很多if…else或者case,会变得比较臃肿,维护成本也比较高,违背开放封闭原则,通过策略模式就可以简化。


/**
 * 开发
 * Created by XQM on 2018/5/13.
 */
public class APPStrategy implements IDevelopStrategy {
    @Override
    public void develop() {
        System.out.println("产品发话了,需要开发APP");
    }
}









/**
 * 具体的策略
 * Created by XQM on 2018/5/13.
 */
public class WebSiteStrategy implements IDevelopStrategy {
    @Override
    public void develop() {
        System.out.println("产品发话了,需要开发网站");






    }
}

IDevelopStrategy

观察者模式:定义对象间一对多的依赖关系,每当一个对象改变状态时,则所有依赖于它的对象都会得到通知并且被自动更新。常见运用在发布-订阅事件总线。

/**
 * 把所有的观察者对象保存在一个集合中,其中每一个主题可以有任意数量的观察者,可以想象为公众号
 * Created by XQM on 2018/5/13.
 */
public interface ObservedSubject {
    /**
     * 增加观察者
     * @param observer
     */
    void add(Observer observer);








    /**
     * 删除观察者
     * @param observer
     */
    void delete(Observer observer);



    /**
     * 通知更新
     * @param message
     */
    void notify(String message);
}




/**
 * 抽象被观察者的实现类,实现添加、删除和通知观察者的方法
 * Created by XQM on 2018/5/13.
 */
public class SubcriptionSubject implements ObservedSubject {
    private List<Observer> subscriberUsers = new ArrayList<Observer>();
    @Override
    public void add(Observer oberver) {
        subscriberUsers.add(oberver);
    }








    @Override
    public void delete(Observer observer) {
        subscriberUsers.remove(observer);
    }


    @Override
    public void notify(String message) {
        for (Observer observer:subscriberUsers){
            observer.update(message);
        }
    }
}





/**
 * 抽象观察者
 * Created by XQM on 2018/5/13.
 */
public interface Observer {
    void update(String message);
}
/**
 * 具体观察者
 * Created by XQM on 2018/5/13.
 */
public class SubscriberUser implements Observer {
    private String name;











    public SubscriberUser(String name) {
        this.name = name;
    }

    @Override
    public void update(String message) {
        System.out.println(name+"更新了:"+message);
    }
}



/**
 * 优点:观察者和被观察者之间是抽象耦合,容易扩展
 * 缺点:在Java中消息的通知一般是按照顺序的,如果每个观察者造成卡顿,会影响整体的效率,采用异步解决
 * Created by XQM on 2018/5/13.
 */
public class ObserverClient {
    public static void main(String[] args){
        SubcriptionSubject subcriptionSubject = new SubcriptionSubject();






        SubscriberUser user1 = new SubscriberUser("下雨了");
        SubscriberUser user2 = new SubscriberUser("下雪了");
        SubscriberUser user3 = new SubscriberUser("落花了");

        //注册订阅
        subcriptionSubject.add(user1);
        subcriptionSubject.add(user2);
        subcriptionSubject.add(user3);


        //发送更新给订阅者
        subcriptionSubject.notify("不一样的博客更新了");

    }


ObservedSubject add  delete Observer notify

public class SubcriptionSubject implements ObservedSubject {
    private List<Observer> subscriberUsers = new ArrayList<Observer>();

 @Override
    public void notify(String message) {
        for (Observer observer:subscriberUsers){
            observer.update(message);
        }
    }





    
    继承Observable类(被观察者发送消息),notifyObservers发送通知
Observable notifyObservers 


Android中MVC、MVP、MVVM的区别与使用
https://www.jianshu.com/p/78e0a508b1c6


Model  View Controller 

Activity/Fragment在View与Controller的定义中有点模糊。

MVP(Model-View-Presenter)是MVC的改良模式。


Model View Presenter做逻辑处理,修改Model

Android 架构设计实现——MVP模式

http://www.voidcn.com/article/p-ztnemdmt-mn.html


基于 MVC(Model View Controller) 模式的 MVP(Model-View-Presenter) 模式应运而生

只要保证我们是通过 Presenter 将 View 和 Model 解耦合、降低类型复杂度、各个模块可以独立测试、独立变化,这就是正确的方向。

IModel IPresenter IView


LoginContract 
 LoginView         LoginPresenter
 
 public class BaseModel implements IModel {
    // 做一些数据处理, 网路请求的初始化操作
}






然后定义交互中间人 LoginPresenter,处理 View 的业务逻辑,它是沟通 View 和 Model 的桥梁,Presenter 持有的 View、Model 引用都是抽象,且经常会执行耗时操作:


Presenter 持有View,Model 引用都是抽象,且经常会执行耗时操作:

LoginPresenter extends BasePresenter<LoginActivity>

getiModelMap().get("login")).login(name, pwd, new LoginModel

getIView().loginSuccess(result); // 成功


vvvvvvvvv决这个问题需要通过弱引用来解决,LoginPresenter 的父类 BasePresenter 如下:

WeakReference IView iview


public class LoginActivity extends AppCompatActivity implements IView, LoginContract.LoginView {

LoginContract.LoginView,IView

MVP的特点
View接受事件,传递给Presenter
Presenter做逻辑处理,修改Model
Model通知Presenter数据变化,Presenter更新View
MVP的优点
将Model与View完全分隔,提高了可扩展性。
便于测试。在测试Presenter时,只要实现View的接口并注入到Presenter就可以测试Presenter的业务逻辑。
MVP的缺点
与MVC一样,P层起到的控制功能伴随着业务的增多,也会变得臃肿。
Presneter需要持有View的引用,同时View也需要持有Presenter的引用,控制上存在一定复杂度。








Presenter

MVP
View -Presenter-Model
Model-Presenter-View

Android DataBinding 从入门到进阶

https://juejin.im/post/6844903609079971854


ViewModel-Presenter        DataBinding

android {
    dataBinding {
        enabled = true
    }
}




dataBinding enabled

layout data 

MVVM

Model  View  data


getRoot

alias = "TempUser"

variable
name type

DataBindingUtil.setContentView

notifyPropertyChangedPro

activityMain2Binding.setUserInfo 


@{userInfo.name}

13

fragmentBlankBinding

ViewDataBinding

实现数据变化自动驱动 UI 刷新的方式有三种:BaseObservable、ObservableField、ObservableCollection


notifyChange        


    android:onClick="@{()->goodsHandler.changeGoodsName()}"

@{()->{}

BaseObservable ObservableField ObservableCollection


DataBindingUtil.setContentView


OnPropertyChangedCallback


onPropertyChanged


 if (propertyId == com.leavesc.databinding_demo.BR.name) {

ObservableParcelable 

ObservableDouble

ObservableField


可通过 ObservableField 泛型来申明其他类型

@{list[index],default =xx}

ObservableArrayList    list 


ObservableMap
DataBindingUtil.setContentView

ObservableArrayMap

setMap  setList

三、双向数据绑定

双向绑定的意思即为当数据改变时同时使视图刷新,而视图改变时也可以同时改变数据

@={}


activityMain10Binding.setGoods 


data -view , view-data

onClick = android:onClick="@{()->userPresenter.onUserNameClick(userInfo)}"
@ {() ->}

include viewStub

include layout

name 
type

在主布局文件中将相应的变量传递给 include 布局,从而使两个布局文件之间共享同一个变量

include
bind

  
        <include
            layout="@layout/view_include"
            bind:userInfo="@{userInfo}" />



bind:userInfo

layout  data import 

variable name  = " "
type = ""

activityMain6Binding.viewStub.getViewStub.inflate

ViewStub 标签懒加载
https://www.jianshu.com/p/9f2e7cf9a0b4


要被加载的布局通过 android:layout 属性来设置. 然后在程序中调用 inflate() 方法来加载. 还可以设定 Visibility 为 VISIBLE 或 INVISIBLE, 也会触发 inflate(). 但只有直接使用 inflate() 方法能返回布局文件的根 View. 但是这里只会在首次使用 setVisibility() 会加载要渲染的布局文件. 再次使用只是单纯的设置可见性.

对 inflate() 操作也只能进行一次, 因为 inflate() 的时候是其指向的布局文件替换掉当前 <ViewStub> 标签. 之后, 原来的布局文件中就没有 <ViewStub> 标签了. 因此, 如果多次 inflate() 操作, 会报错: ViewStub must have a non-null ViewGroup viewParent

inflate

<ViewStub> 标签实质上是一个宽高都为 0 的不可见 View. 通过延迟加载布局的方式优化布局提升渲染性能.


Android性能优化之一:ViewStub
https://www.cnblogs.com/lwbqqyumidi/p/4047108.html

.布局文件inflate时,ViewStub主要是作为一个“占位符”的性质,放置于view tree中,且ViewStub本身是不可见的。ViewStub中有一个layout属性,指向ViewStub本身可能被替换掉的布局文件,在一定时机时,通过viewStub.inflate()完成此过程;


viewStub.inflate

layout ViewStub


viewStub.infalte()或viewStub.setVisibility(View.VISIBLE)来完成;
 if (noDataView == null) {
 4         ViewStub noDataViewStub = (ViewStub) view.findViewById(R.id.no_data_viewstub);
 5         noDataView = noDataViewStub.inflate();
 6     } else {
 7         noDataView.setVisibility(View.VISIBLE);
 8     }







结合ViewStub“占位符”可以比较好的完成此类需求


ViewStub layout bind:userInfo = "@{userInfo}"


     activityMain6Binding.viewStub.setOnInflateListener(new ViewStub.OnInflateListener() {
            @Override
            public void onInflate(ViewStub stub, View inflated) {
   //如果在 xml 中没有使用 bind:userInfo="@{userInf}" 对 viewStub 进行数据绑定
                //那么可以在此处进行手动绑定
                ViewStubBinding viewStubBinding = DataBindingUtil.bind(inflated);
                viewStubBinding.setUserInfo(user);
                Log.e(TAG, "onInflate");








    ActivityMain6Binding activityMain6Binding = DataBindingUtil.setContentView(this, R.layout.activity_main6);
    View view = activityMain6Binding.viewStub.getViewStub().inflate();


   ViewStubBinding viewStubBinding = DataBindingUtil.bind(inflated);

   
   
   DataBindingUtil.bind inflated


例如,对于一个 ImageView ,我们希望在某个变量值发生变化时,可以动态改变显示的图片,此时就可以通过 BindingAdapter 来实现


BindingAdapter("url")

loadImage   

<data   <variable     name = "image"

<ConstraintLayout

 bind:url="@{image.url}" />


BindingConversion

@{String}    -conversionString

BindingConversion background textColor    

background->Drawable    textColor->Color

Array List Set Map&lt

dataBinding     list[index]


SparseArray

variable array String[]

list    map

  android:text='@{@string/format("leavesC", "Ye")}'
  
  @{@string/format("","")}

三.MVVM
MVVM实现了数据与UI的双重绑定,其中DataBinding是实现MVVM的关键工具。

Model
与MVC和MVP一样,Model层保存了业务数据与处理方法
View
对应Activity以及XML,但是比起MVC与MVP框架中的View层,更加简洁
ViewModel
负责实现View与Model的交互,将两者分离




MVVM  Model View  ViewModel  DataBinding


View     -  ViewModel  - Model


  MVVM的特点
View接受事件,转交给ViewModel
ViewModel操作Model更新数据
Model更新后通知ViewModel,ViewModel更新View数据
MVVM的优点
低耦合。由于ViewModel的存在,View可以独立于Model变化与修改;同理,Model也可以独立于View变化与修改。
可重用性。一个ViewModel可被多个View重复绑定,实现同一组业务。
ViewModel中解决了MVP中V-P互相持有引用的问题,使得结构更清晰,简洁
MVVM的缺点
ViewModel持有Model的依赖。
数据绑定方式使得bug难以确定是在View中还是在Model中。











MVVM  ViewModel   MVP V-P ->View,Presenter
  

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!