使用新的android架构(MVVM)

时间:2017-10-11 08:11:19

标签: android mvvm

目标是从Fragment获取信息,以便托管Activity可以显示该信息。我们举一个简单的例子,假设当Fragment更改时,我们希望在Fragment的操作栏中显示Activity的标题。

这是我过去的做法:

Activity

@Override
protected void onCreate( @Nullable Bundle savedInstanceState )
{
    super.onCreate( savedInstanceState );

    getSupportFragmentManager().addOnBackStackChangedListener( this );
}

@Override
public void onBackStackChanged( )
{
    BaseFragment fragment = mNavigationManager.getCurrentFragment( );

    if( fragment != null && fragment instanceof ActionBarProvider )
        mActionBarTitle.setText( ( ( ActionBarProvider ) fragment ).getTitle( ) );
}

ActionBarProvider

public interface ActionBarProvider
{
    String getTitle( );
}

片段

// implements ActionBarProvider

@Override
protected String getTitle( )
{
    return "Hello world";
}

以下是我对MVVM的看法:

活动

@Override
protected void onCreate( @Nullable Bundle savedInstanceState )
{
    super.onCreate( savedInstanceState );

    mViewModel = ViewModelProviders.of( this, mViewModelFactory ).get( MainViewModel.class );
    mViewModel.getTitle( ).observe( this, s -> mActionBarTitle.setText( s ) );
}

MainViewModel

private MutableLiveData< String > mTitle = new MutableLiveData<>( );

public MutableLiveData< String > getTitle( )
{
    return mTitle;
}

public void setTitle( String title )
{
    mTitle.postValue( title );
}

片段

@Override
public void onActivityCreated( @Nullable Bundle savedInstanceState )
{
    super.onActivityCreated( savedInstanceState );

    MainViewModel viewModel = ViewModelProviders
            .of( getActivity( ), mViewModelFactory )
            .get( MainViewModel.class );

    viewModel.setTitle( "hello world" );
}

MVVM看起来更干净,但它假设Fragment知道它的主要Activity ViewModel:

MainViewModel viewModel = ViewModelProviders
            .of( getActivity( ), mViewModelFactory )
            .get( MainViewModel.class );

因此,如果您将Fragment移至另一个Activity,那么这项工作就无法完成。 我应该保持旧的方式吗?或者你们有其他方式使用MVVM进行这种通信吗?

THX!

1 个答案:

答案 0 :(得分:5)

使用ViewModel是一条黄金法则。除了* .arch软件包之外,导入中以Android软件包开头的所有内容都是错误的。

你没有在你的行动中设置标题,因为它与片段绑定。

在片段中的getActivity().setTitle() / onStart方法中使用onResume

ViewModels绑定到片段OR或主机活动。更改活动也会在ViewModel中调用onCleared()。您无法使用ViewModel在多个活动之间共享数据。

创建共享数据的接口不是MVVM。它是MVP,应该避免使用MVVM和Google's AAC

由于多个活动可能是您的片段的主机,因此您永远不应直接访问该活动。最好在片段中使用if (getActivity() != null) { getActivity().setTitle(...) }

顺便说一下,如果你不修改getter / setter,你也应该使用public final LiveData并避免使用getter和setter。您的LiveData实例不会发生变化,但数据会发生变化。方法final就好了。

public final LiveData<String> mTitle = new MutableLiveData<String>();

如果您不想附加数据,还应该考虑使用setValue()来设置数据。

因此,如果您将片段移动到另一个活动,这将无法正常工作。我应该保持旧的方式吗?或者你们有其他方式使用MVVM进行这种通信吗?

ViewModel只能在片段和托管活动之间共享,但它不能使用多个活动共享。