我一直在努力寻找在Android中实现MVVM的正确方法.
整个想法对我来说仍然模糊,模式是有一个单独的层,逻辑完成(ViewModel).
这段代码只能动画一堆片段所在的背景的alpha.
public class StartActivity extends AppCompatActivity implements EntryFragment.EntryFragementListener {
private static final float MINIMUM_ALPHA = 0.4f;
private static final float MAXIMUM_ALPHA = 0.7f;
@State
float mCurrentAlpha = MINIMUM_ALPHA;
@State
String mCurrentTag = EntryFragment.TAG;
private ActivityStartBinding mBinding;
private StartViewModel mStartViewModel = new StartViewModel();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_start);
mBinding.setStartViewModel(mStartViewModel);
mBinding.bgBlackLayer.setAlpha(mCurrentAlpha);
if (getSupportFragmentManager().findFragmentByTag(mCurrentTag) == null) {
switch (mCurrentTag) {
case EntryFragment.TAG:
setEntryFragment();
break;
case FreeTrialFragment.TAG:
setFreeTrialFragment();
break;
}
}
}
private void setEntryFragment() {
mCurrentAlpha = MINIMUM_ALPHA;
mCurrentTag = EntryFragment.TAG;
FragmentManager fm = getSupportFragmentManager();
Fragment fragment = new EntryFragment();
fm.beginTransaction().
add(R.id.fragment_content, fragment, EntryFragment.TAG).commit();
}
private void setFreeTrialFragment() {
mCurrentTag = FreeTrialFragment.TAG;
Fragment fragment = new FreeTrialFragment();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setCustomAnimations(R.anim.anim_enter_right, R.anim.anim_exit_left, R.anim.anim_enter_left, R.anim.anim_exit_right);
ft.replace(R.id.fragment_content, fragment, FreeTrialFragment.TAG);
ft.addToBackStack(FreeTrialFragment.TAG);
ft.commit();
StartViewModel.setAnimation(mBinding.bgBlackLayer,true, MAXIMUM_ALPHA);
}
private void setForgotPasswordFragmet() {
}
private void setLoginFragment() {
}
@Override
public void onBackPressed() {
super.onBackPressed();
StartViewModel.setAnimation(mBinding.bgBlackLayer,true, MINIMUM_ALPHA);
mCurrentAlpha = MINIMUM_ALPHA;
}
@Override
public void onEntryLoginButton() {
setLoginFragment();
}
@Override
public void onEntryFreeTrialButton() {
setFreeTrialFragment();
}
}
Run Code Online (Sandbox Code Playgroud)
-ViewModel只执行动画中的逻辑-Fragments有一个监听器将事件传递给活动-Binding有助于定义视图
public class StartViewModel {
public ObservableBoolean hasToAnimate = new ObservableBoolean(false);
public float alpha;
@BindingAdapter(value={"animation", "alpha"}, requireAll=false)
public static void setAnimation(View view, boolean hasToAnimate, float alpha) {
if (hasToAnimate) {
view.animate().alpha(alpha);
}
}
}
Run Code Online (Sandbox Code Playgroud)
问题是,是否所有逻辑都存在于视图模型中,包括片段事务,方向变更管理等等?有没有更好的方法来实现MVVM?
至于我 - MVVM,MVP和其他非常酷的模式真的很酷的家伙没有简单的收据/流量.当然,您有很多教程/建议/模式和方法如何实现它们.但这实际上就是所有编程的内容 - 您只需要提出一个满足您需求的解决方案.根据您的开发人员愿景,您可以将许多原则应用于您的解决方案,以便更容易/更快地开发/测试/支持.
在你的情况下,我认为最好将这种逻辑移动到Fragment过渡(正如你所做的那样setFreeTrialFragment()),它更易于定制和使用.但是,如果你的方法应该保持不变 - 现有方法是正常的.实际上@BindingAdapter更适合xml属性然后直接使用.
至于我 - 所有的UI逻辑都应该驻留在Activity中,主要目的是将业务逻辑与UI分开.因为所有的动画,片段交易等都是在活动内部处理的 - 这是我的方法.ViewModel - 负责通知视图相应模型中的某些内容已更改,并且视图应自行安排这些更改.在完美的世界中,你应该能够实现像双向绑定这样的流行术语,但并不总是必要的,并且不应总是在ViewModel内部处理UI更改.像往常一样,过多的MVVM对你的项目不利.它可以导致意大利面条代码,"它来自哪里?","如何回收视图?" 和其他流行的问题.因此,它应该只用于让生活变得更加生动,而不是让一切都变得理想,因为像其他所有模式一样,它会让人头疼,有人会仔细查看你的代码会说"OVERENGINEERING !! 11".
这里有一些有用的文章:
简短示例(通用),您应该适合您的架构:
实施:
型号:
public class GalleryItem {
private String mImagePath;
//other variables/getters/setters
}
Run Code Online (Sandbox Code Playgroud)
主持人 :
//cool presenter with a lot of stuff
public class GalleryPresenter {
private GalleryView mGalleryView;
public void loadPicturesBySomeCreteria(Criteria criteria){
//perform loading here
//notify your activity
mGalleryView.setGalleryItems(yourGaleryItems);
}
//you can use any other suitable name
public void bind(GalleryView galleryView) {
mGalleryView = galleryView;
}
public void unbind() {
mGalleryView = null;
}
//Abstraction for basic communication with activity.
//We can say that this is our protocol
public interface GalleryView {
void setGalleryItems(List<GalleryItem> items);
}
}
Run Code Online (Sandbox Code Playgroud)
查看:
public class NiceGalleryView extends View {
public NiceGalleryView(Context context) {
super(context);
}
public NiceGalleryView(Context context, AttributeSet attrs) {
super(context, attrs);
}
// TODO: 29.12.16 do your stuff here
}
Run Code Online (Sandbox Code Playgroud)
并且cource活动代码:
public class GalleryActivity extends AppCompatActivity implements GalleryPresenter.GalleryView {
private GalleryPresenter mPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gallery);
//init views and so on
mPresenter = new GalleryPresenter();
mPresenter.bind(this);
}
@Override
public void setGalleryItems(List<GalleryItem> items) {
//use RecyclerView or any other stuff to fill your UI
}
@Override
protected void onDestroy() {
super.onDestroy();
mPresenter.unbind();
}
}
Run Code Online (Sandbox Code Playgroud)
还要注意,在使用MVP时,您甚至有很多不同的方法.我只想强调,我更喜欢在活动中初始化视图,而不是将它们从活动中传递出去.您可以通过界面进行管理,这不仅适用于开发,甚至适用于仪器测试.
| 归档时间: |
|
| 查看次数: |
1678 次 |
| 最近记录: |