使用新的Android架构(MVVM)的活动片段通信

Sam*_*net 4 android mvvm

目标是从a获取信息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( ) );
}
Run Code Online (Sandbox Code Playgroud)

ActionBarProvider

public interface ActionBarProvider
{
    String getTitle( );
}
Run Code Online (Sandbox Code Playgroud)

分段

// implements ActionBarProvider

@Override
protected String getTitle( )
{
    return "Hello world";
}
Run Code Online (Sandbox Code Playgroud)

以下是我对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 ) );
}
Run Code Online (Sandbox Code Playgroud)

MainViewModel

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

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

public void setTitle( String title )
{
    mTitle.postValue( title );
}
Run Code Online (Sandbox Code Playgroud)

分段

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

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

    viewModel.setTitle( "hello world" );
}
Run Code Online (Sandbox Code Playgroud)

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

MainViewModel viewModel = ViewModelProviders
            .of( getActivity( ), mViewModelFactory )
            .get( MainViewModel.class );
Run Code Online (Sandbox Code Playgroud)

所以,如果你转移Fragment到另一个,Activity这将无法正常工作.我应该保持旧的方式吗?或者你们有其他方式使用MVVM进行这种通信吗?

谢谢!

Ema*_*l S 5

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

您没有在动作中设置标题,因为它与片段绑定.

getActivity().setTitle()在片段中的onStart/ onResumemethod中使用.

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

创建共享数据的接口不是MVVM.它是MVP,应该避免使用MVVM和谷歌的AAC.

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

顺便说一句,如果你不修改getter/setter,你也应该使用public final LiveData并避免使用getter和setter.您的LiveData实例不会更改,但数据会更改.手段final很好.

public final LiveData<String> mTitle = new MutableLiveData<String>();
Run Code Online (Sandbox Code Playgroud)

setValue()如果您不想附加但是替换数据,您还应该考虑使用设置数据.

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

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