It's been almost 3 years, but I think it may be helpful for somebody. This example uses MVP pattern. BaseNetContentActivity, BaseNetContentFragment and NetworkErrorFragment are encapsulate change UI logic (by fragments' swapping), in case of network error. They should be extended by other classes.
1) BaseNetContentView.java - base interface for all Views, that should show "network error" UI.
public interface BaseNetContentView {
public void showNetworkContentError();
}
2) BaseNetContentFragment.java - base for all Fragments, that should show "network error" UI. It contains listener and corresponding interface.
public abstract class BaseNetContentFragment extends Fragment implements BaseNetContentView {
@Nullable
private OnNetworkErrorListener mOnNetworkErrorListener;
protected final void tryToShowNetworkError() {
if (mOnNetworkErrorListener != null) {
mOnNetworkErrorListener.onNetworkError();
}
}
protected final boolean hasOnNetworkErrorListener() {
return mOnNetworkErrorListener != null;
}
public final void setOnNetworkErrorListener(
@Nullable OnNetworkErrorListener onNetworkErrorListener) {
mOnNetworkErrorListener = onNetworkErrorListener;
}
public interface OnNetworkErrorListener {
public void onNetworkError();
}
}
3) BaseNetContentActivity - base Activity, that handling network error by changing UI fragments
public abstract class BaseNetContentActivity<T extends BaseNetContentFragment>
extends AppCompatActivity implements BaseNetContentFragment.OnNetworkErrorListener {
private static final String TAG = "BaseNetContentActivity";
@Override
public void onNetworkError() {
FragmentManager fragmentManager = getSupportFragmentManager();
Fragment fragment = getCurrentContentFragment(fragmentManager);
// Skip if already NetworkErrorFragment
if (!(fragment instanceof NetworkErrorFragment)) {
setFragmentToActivity(fragmentManager, new NetworkErrorFragment());
}
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutResId());
Fragment fragment = getCurrentContentFragment(getSupportFragmentManager());
// NetworkErrorFragment is self-sufficient
if (fragment instanceof NetworkErrorFragment) {
return;
}
setNetworkContentFragmentToActivity(savedInstanceState);
}
@Override
public void onAttachFragment(Fragment fragment) {
// Set appropriate listener to fragment
if (fragment instanceof NetworkErrorFragment) {
((NetworkErrorFragment) fragment)
.setOnReloadContentListener(new NetworkErrorFragment.OnReloadContentListener() {
@Override
public void onReloadContent() {
setNetworkContentFragmentToActivity(null);
}
});
} else if (fragment instanceof BaseNetContentFragment) {
((BaseNetContentFragment) fragment).setOnNetworkErrorListener(this);
}
// Don't do anything with other fragment's type
}
@NonNull
protected abstract T createNetworkContentFragment();
protected abstract void setPresenter(@NonNull T fragment, @Nullable Bundle savedInstanceState);
@LayoutRes
protected int getLayoutResId() {
return R.layout.basenetworkcontent_act;
}
@IdRes
protected int getContentFrameId() {
return R.id.network_content_frame;
}
private void setNetworkContentFragmentToActivity(@Nullable Bundle savedInstanceState) {
FragmentManager fragmentManager = getSupportFragmentManager();
Fragment fragment = getCurrentContentFragment(fragmentManager);
if (fragment == null || fragment instanceof NetworkErrorFragment) {
fragment = createNetworkContentFragment();
}
try {
setPresenter((T) fragment, savedInstanceState);
} catch (ClassCastException e) {
// Unexpected fragment type
Log.d(TAG,"Can't set Presenter because of wrong View type (wrong fragment)" + e);
// Casting to T type is safe, because createNetworkFragment() returns T type
fragment = createNetworkContentFragment(); // returns type T
setPresenter((T) fragment, savedInstanceState);
}
setFragmentToActivity(fragmentManager, fragment);
}
private Fragment getCurrentContentFragment(@NonNull FragmentManager fragmentManager) {
return fragmentManager.findFragmentById(getContentFrameId());
}
private void setFragmentToActivity(@NonNull FragmentManager fragmentManager,
@NonNull Fragment fragment) {
fragmentManager.beginTransaction()
.replace(getContentFrameId(), fragment)
.commit();
}
}
4) NetworkErrorFragment
public static class NetworkErrorFragment extends Fragment implements View.OnClickListener {
@Nullable
private OnReloadContentListener mOnReloadContentListener;
private Button mReloadButton;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.networkerror_frag, container, false);
mReloadButton = (Button) root.findViewById(R.id.reload_content_button);
if (mOnReloadContentListener != null) {
mReloadButton.setOnClickListener(this);
} else {
mReloadButton.setVisibility(View.INVISIBLE);
}
return root;
}
@Override
public void onClick(View v) {
if (mOnReloadContentListener != null) {
mOnReloadContentListener.onReloadContent();
}
}
public void setOnReloadContentListener(@Nullable OnReloadContentListener onReloadContentListener) {
mOnReloadContentListener = onReloadContentListener;
}
public interface OnReloadContentListener {
public void onReloadContent();
}
}
Full example at https://github.com/relativizt/android-network-error-ui