浅谈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<
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
来源:oschina
链接:https://my.oschina.net/u/4390958/blog/4627304