我一直在关注Google提供的MVP设计模式来重构我的应用程序。我有一个MainActivity和许多片段,我为每个片段创建活动似乎很麻烦,所以我一直在考虑在片段中注册演示者。我所看到的是每个片段都注册了它自己的主持人,但我不确定它有多大错...:)
所以这是我的演讲者:
public class FirstPresenter implements FirstContract.Presenter {
private final FirstContract.View mView;
public FirstPresenter(FirstContract.View view) {
mView = view;
}
@Override
public void start() {
Log.e(TAG, "Start");
}
}
这是我的片段:
public class FirstFragment extends Fragment implements FirstContract.View {
private FirstContract.Presenter mPresenter;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container
, Bundle savedInstanceState) {
...
// I register firstFragment's presenter here.
mPresenter = new FirstPresenter(this);
...
所以我的问题是,这是正确的方法吗?我可以在活动中将Presenter注册到Fragment中吗?如果不是正确的方法,是否有一些很好的例子来处理一个活动和多个片段的MVP?
谢谢你们, BR!
答案 0 :(得分:18)
正如您在 Google的示例(https://github.com/googlesamples/android-architecture)中看到的那样,Activities
创建了Presenters
。另外Views
附加到Activity
和Presenters
获取视图(Fragments
)作为参数。
提交Fragment
事务或Fragment
(查看)状态恢复后创建Presenters
并将Fragments
(视图)作为参数而不是调用
view.setPresenter(T presenter);
视图方法和Presenters
已注册查看。
我认为在Presenter
中创建Fragment
不是一个好习惯。首先,它们是单独的图层。这对于关注点分离是违法的。第二,如果您在Fragment
中创建演示者,则将Presenter的生命绑定到视图的LifeCycle
,当Fragment
被销毁并重新创建时,您将创建一个新的演示者,但它们是不同的层。
模型是一个界面,用于定义要在用户界面中显示或以其他方式操作的数据。
演示者对模型和视图起作用。它从存储库(模型)中检索数据,并将其格式化以在视图中显示。
视图是一个被动接口,它显示数据(模型)并将用户命令(事件)路由到演示者以对该数据进行操作。
因此Activity
可以充当overall controller
,可以创建Presenters
和Views
并连接它们。
如果我们谈论您的问题,是的,您可以在片段中注册演示者。但是,您应该避免在用作视图的片段中创建演示者。
但是在Android社区中有很多关于MVP模式的方法,如下所示。 https://plus.google.com/communities/114285790907815804707
为什么活动不是ui元素? http://www.techyourchance.com/activities-android/
答案 1 :(得分:0)
如果您使用一个活动来托管多个片段,并且还使用Dagger 2插入演示者,则可以将每个演示者直接注入每个片段。
自从我发现有关Android jetpack导航组件的几个月以来,我一直在做一个带有体系结构的项目,我开始将所有应用程序视图迁移到这种模式。
因此,我在执行该过程时遇到了很多重构,而我处于这种情况,不知道该如何处理。
由于我从一开始就使用Dagger 2将演示者注入到我的“活动”中,因此使用Fragments所做的改变不会太大。
我在同一个存储库中检查了Fragments应该遵循的体系结构,如果您只有1个Fragment,那么这确实是在活动Activity中实例化演示者的一种好方法。
问题是,如果我需要在一个主机活动中包含多个片段,则应为每个演示者创建一个实例,并将其通过每个片段内的FragmentManager传递,我认为这不是我正在查看的内容,因为它添加了多个片段主持人活动中演示者的实例化。
这导致一种情况,在我的主持人活动中的所有演示者都有多个实例,并且在需要时还提供一些接口来处理作业/视图的分离。
处理多个片段的一种简单方法就是不考虑主机活动,而是将演示者注入每个片段本身中。
由于使用Dagger进行了此操作,因此可以使注射更清洁。
看一个简单的例子
class MainMenuActivity : BaseActivity(){
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
inflateMainFragment(savedInstanceState)
}
override fun getLayout(): Int {
return R.layout.activity_main_menu
}
fun inflateMainFragment(savedInstanceState: Bundle?){
if (savedInstanceState == null) {
val fragment = MainMenuFragment()
supportFragmentManager
.beginTransaction()
.add(R.id.nav_host_fragment, fragment)
.commit()
}
}
}
如您所见,在这里,我没有导航所需的任何演示者的任何实例化。相反,我只是将我需要的每个演示者注入每个Fragment
class MapsFragment: BaseMapFragment(), MapContract.MapView {
private lateinit var mMap: GoogleMap
@Inject
lateinit var presenter: MapsPresenter
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_paseo,container,false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
(requireActivity().application as YawpApplication).getAppComponent()?.inject(this)
presenter.attachView(this)
setupToolbar()
setupMap()
}
}
利用Fragments生命周期,您可以使用onDestroyView()
方法分离所有Fragments视图,并在运行垃圾收集器时节省一些内存空间。
override fun onDestroyView() {
super.onDestroyView()
presenter.detachView()
presenter.detachJob()
}
我在Google的官方仓库中发现了一个可以帮助我更好地理解它的问题。
您可以here
检查它