已经快 3 年了,但我认为这可能对某人有所帮助。此示例使用 MVP 模式。BaseNetContentActivity、BaseNetContentFragment 和 NetworkErrorFragment 封装了更改 UI 逻辑(通过片段的交换),以防网络错误。它们应该由其他类扩展。
1) BaseNetContentView.java - 所有视图的基本接口,应该显示“网络错误”UI。
public interface BaseNetContentView {
public void showNetworkContentError();
}
2) BaseNetContentFragment.java - 所有片段的基础,应该显示“网络错误”UI。它包含监听器和相应的接口。
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 - 基础 Activity,通过改变 UI 片段来处理网络错误
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) 网络错误片段
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();
}
}
完整示例在https://github.com/relativizt/android-network-error-ui