具有相同功能的活动和片段
Posted
技术标签:
【中文标题】具有相同功能的活动和片段【英文标题】:Activities and fragments with the same features 【发布时间】:2021-12-05 14:34:37 【问题描述】:我有相同的 UI 相关功能和实现,我想在 Activity
和 Fragment
中使用一次。如何实现架构以避免重复代码?
在Activity
中显示Fragment
会降低性能吗?
我的目标是为其他类实现一个abstract class
以使用分页。子类有时是Activity
类型,有时是Fragment
类型。
我设计了一个interface
,它具有以下方法。然后我在abstract Fragment
类中实现了这些功能:
public interface PaginableComponent
void onRequestList();
void onSuccessLoadList(@NonNull List<Paginable> list);
void onErrorLoadList(String errorMessage);
void onRequestLoadMoreList(int oldTotalCount);
void onSuccessLoadMore(@NonNull List<Paginable> list);
void onTryLoadList();
@NonNull
PaginableAdapter getAdapter();
这是实现此接口的abstract Fragment
类:
public abstract class PaginableFragment extends BaseFragment
implements PaginableComponent, PaginableAdapter.LoadListMoreListener
private final AtomicBoolean mIsFirstLoadedList = new
AtomicBoolean(false);
private SwipeRefreshLayout mSwipeRefreshLayout;
private View mStatusLayout;
private ProgressBar mStatusProgressBar;
private TextView mStatusMessageTextView;
private TextView mTryAgainTextView;
public Boolean isHidden = true;
@CallSuper
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState)
super.onViewCreated(view, savedInstanceState);
initViews(view);
getAdapter().setLoadListMoreListener(this);
if (mSwipeRefreshLayout != null)
mSwipeRefreshLayout.setColorSchemeColors(UiUtils.getStyleColor(requireContext(), R.attr.colorPrimary));
mSwipeRefreshLayout.setOnRefreshListener(this::checkNetAndRequestList);
@Override
public void onPause()
super.onPause();
isHidden = true;
@Override
public void onResume()
super.onResume();
isHidden = isHidden();
@Override
public void onHiddenChanged(boolean hidden)
super.onHiddenChanged(hidden);
isHidden = hidden;
private void initViews(View view)
mSwipeRefreshLayout = view.findViewById(R.id.swipeRefreshLayout);
mStatusLayout = view.findViewById(R.id.statusLayout);
if (mStatusLayout != null)
mStatusProgressBar = mStatusLayout.findViewById(R.id.progressBar);
mStatusMessageTextView = mStatusLayout.findViewById(R.id.text);
mTryAgainTextView = mStatusLayout.findViewById(R.id.tryAgain);
mTryAgainTextView.setOnClickListener(v -> onTryLoadList());
protected void showStatus(String type)
if (mStatusLayout != null)
switch (type)
case Messages.MSG_LOADING:
mStatusProgressBar.setVisibility(View.VISIBLE);
mStatusMessageTextView.setVisibility(View.GONE);
mTryAgainTextView.setVisibility(View.GONE);
break;
case Messages.MSG_NET:
mStatusMessageTextView.setText(R.string.no_network_connection);
mStatusProgressBar.setVisibility(View.GONE);
mStatusMessageTextView.setVisibility(View.VISIBLE);
mTryAgainTextView.setVisibility(View.VISIBLE);
break;
case Messages.MSG_ERROR:
mStatusMessageTextView.setText(R.string.sorry_unexpected_error_occurred);
mStatusProgressBar.setVisibility(View.GONE);
mStatusMessageTextView.setVisibility(View.VISIBLE);
mTryAgainTextView.setVisibility(View.GONE);
break;
mStatusLayout.setVisibility(View.VISIBLE);
private void hideStatus()
if (mStatusLayout != null)
mStatusLayout.setVisibility(View.GONE);
@CallSuper
@Override
public void onSuccessLoadList(@NonNull List<Paginable> list)
mIsFirstLoadedList.set(true);
if (mSwipeRefreshLayout != null)
mSwipeRefreshLayout.setRefreshing(false);
hideStatus();
getAdapter().resetList(list);
@CallSuper
@Override
public void onErrorLoadList(String errorMessage)
if (mSwipeRefreshLayout != null)
mSwipeRefreshLayout.setRefreshing(false);
showStatus(Messages.MSG_ERROR);
getAdapter().setIsLoadingMore(false);
@CallSuper
@Override
public void onLoadListMore(int oldTotalCount)
getAdapter().showEndMessage(Paginable.TYPE_SHIMMER);
if (NetReceiver.isNetConnected(requireContext()))
onRequestLoadMoreList(oldTotalCount);
else
showStatus(Messages.MSG_NET);
@CallSuper
@Override
public void onSuccessLoadMore(@NonNull List<Paginable> list)
if (mSwipeRefreshLayout != null)
mSwipeRefreshLayout.setRefreshing(false);
hideStatus();
getAdapter().hideEndMessages();
getAdapter().addList(list);
getAdapter().setIsLoadingMore(false);
@CallSuper
@Override
public void onTryLoadList()
if (!mIsFirstLoadedList.get())
checkNetAndRequestList();
@Override
public void onNetEvent(NetReceiver.NetEvent event)
if (event.isConnected())
hideStatus();
if (!mIsFirstLoadedList.get())
getAdapter().clearAndInitShimmers();
onRequestList();
if (getAdapter().isLoadingMore())
onRequestLoadMoreList(getAdapter().getItemCount());
else
showStatus(Messages.MSG_NET);
public void checkNetAndRequestList()
if (NetReceiver.isNetConnected(requireContext()))
if (!mIsFirstLoadedList.get())
getAdapter().clearAndInitShimmers();
onRequestList();
else
if (mSwipeRefreshLayout != null)
mSwipeRefreshLayout.setRefreshing(false);
showStatus(Messages.MSG_NET);
if (!mIsFirstLoadedList.get())
getAdapter().clearAndInitNoInternet();
现在我想在活动中使用相同的实现。
【问题讨论】:
我认为你应该检查the guidelines on how to ask questionsuse once in Activity and again in Fragment
这意味着你在活动中真的不需要它,你只需要使用相同的片段两次,对吧? Does displaying a Fragment in an Activity reduce performance?
为什么会这样?它会产生足够的改变来改变任何东西吗?没有
【参考方案1】:
防止重复代码的一种方法是在 MVVM 架构中使用 ViewModel
和 LiveData
。
【讨论】:
但是我的大部分代码都和UI实现有关。以上是关于具有相同功能的活动和片段的主要内容,如果未能解决你的问题,请参考以下文章
从活动向上导航到片段打开相同的片段 - Android 导航组件
在 TabLayout 和 ViewPager2 中执行异步任务后更新具有相同布局的多个片段