2017年6月12日更新:
Android官方提供了一个简单、精确的示例,用于演示Master-Detail模板下ViewModel的工作原理。您应该先查看一下此示例。
正如@CommonWare、@Quang Nguyen所提到的,Yigit的目的不是从主控制器调用细节控制器,而是更好地使用中介者模式。但如果您想进行一些片段事务处理,则应在活动中完成。此时,ViewModel类应该作为活动中的静态类,并可能包含一些丑陋的回调来回调活动并使片段事务处理。
我尝试实现了这个功能,并做了一个简单的项目。您可以查看一下。大部分代码都是引用自Google IO 2017,也是结构的一部分。
https://github.com/charlesng/SampleAppArch
我没有使用Master Detail Fragment来实现组件,而是使用旧的(在ViewPager中的片段之间通信)。逻辑应该是相同的。
但我发现使用这些组件很重要的是:
- 您希望在中介者中发送和接收的内容应仅在ViewModel中发送和接收。
- 片段类中的修改似乎不太多。因为它只是将实现从“接口回调”更改为“监听并响应ViewModel”
- View Model的初始化似乎很重要,可能会在活动中被调用。
- 使用MutableLiveData只在活动中使源同步。
1. Pager Activity
public class PagerActivity extends AppCompatActivity {
private ViewPager mPager;
private PagerAgentViewModel pagerAgentViewModel;
private PagerAdapter mPagerAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pager);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
mPager = (ViewPager) findViewById(R.id.pager);
mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
pagerAgentViewModel = new ViewModelProvider(this).get(PagerAgentViewModel.class);
pagerAgentViewModel.init();
}
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
...Pager Implementation
}
}
2.分页代理视图模型(它应该有一个比这更好的名称)
public class PagerAgentViewModel extends ViewModel {
private final SavedStateHandle state;
private final MutableLiveData<String> messageContainerA;
private final MutableLiveData<String> messageContainerB;
public PagerAgentViewModel(SavedStateHandle state) {
this.state = state;
messageContainerA = state.getLiveData("Default Message");
messageContainerB = state.getLiveData("Default Message");
}
public void sendMessageToB(String msg)
{
messageContainerB.setValue(msg);
}
public void sendMessageToA(String msg)
{
messageContainerA.setValue(msg);
}
public LiveData<String> getMessageContainerA() {
return messageContainerA;
}
public LiveData<String> getMessageContainerB() {
return messageContainerB;
}
}
3.空白片段A
public class BlankFragmentA extends Fragment {
private PagerAgentViewModel viewModel;
public BlankFragmentA() {
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
viewModel = new ViewModelProvider(getActivity()).get(PagerAgentViewModel.class);
textView = (TextView) view.findViewById(R.id.fragment_textA);
Button button = (Button) view.findViewById(R.id.btnA);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
viewModel.sendMessageToB("Hello B");
}
});
viewModel.getMessageContainerA().observe(getViewLifecycleOwner(), new Observer<String>() {
@Override
public void onChanged(@Nullable String msg) {
textView.setText(msg);
}
});
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_blank_a, container, false);
return view;
}
}
4.空白片段B
public class BlankFragmentB extends Fragment {
public BlankFragmentB() {
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
viewModel = new ViewModelProvider(getActivity()).get(PagerAgentViewModel.class);
textView = (TextView) view.findViewById(R.id.fragment_textB);
Button button = (Button) view.findViewById(R.id.btnB);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
viewModel.sendMessageToA("Hello A");
}
});
viewModel.getMessageContainerB().observe(getViewLifecycleOwner(), new Observer<String>() {
@Override
public void onChanged(@Nullable String msg) {
textView.setText(msg);
}
});
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_blank_b, container, false);
return view;
}
}