使用“点击重试”选项在 Android 中显示 android 中的网络错误的最佳方法

Best approach to show network error in android in Android with Tap to Retry option

我的申请中有 Navigation Drawer,除了主要申请流程外,还有几个 Fragments 和几个新的 Activity

由于内部Fragments处理回调可能很麻烦,如何有效地处理这种情况?
对于单个 Activity,这可以轻松实现,但担心导航抽屉和内部 Fragments。
有什么建议吗?

您可以在FrameLayout中放置一些ContentFragment,然后在网络断开时替换为NetworkDisconnectedFragment。这将需要按钮调用回调,然后在重新连接时,在回调实现中将 NetworkDisconnectedFragment 替换为旧的 ContentFragment

将此错误布局隐藏在此片段中。当出现任何网络错误时,将其可见性更改为 VISIBLE。并在此隐藏布局中添加一个按钮以调用相同的方法来检查网络连接等。

假设你有片段 xml 比如 - 片段-
相对布局包括 - 1.-所有布局(可见)& 2. - 带有按钮的隐藏网络错误布局(消失)

当出现网络错误时,将 1. 的可见性更改为 - GONE 和 2. 对 VISIBLE

的可见性

和重试按钮调用 -

checkNetworkConnectionCall(); 

希望这能解决您的问题。

您可以在每个片段中包含此 UI 并创建一个 BaseFragment,它将被导航抽屉中的每个片段扩展。

在该基本片段中编写一个方法来完成更改 UI 所需的完整逻辑。

每当您检测到网络故障时,只需从那里的基本片段中盲目调用该方法即可。

已经将近 3 年了,但我认为它可能对某些人有所帮助。此示例使用 MVP 模式。 BaseNetContentActivity、BaseNetContentFragment 和NetworkErrorFragment 封装了变化UI 逻辑(通过分片交换),以防网络错误。它们应该由其他 类.

扩展

1) BaseNetContentView.java - 所有视图的基本界面,应显示 "network error" UI。

public interface BaseNetContentView {
    public void showNetworkContentError();
}

2) BaseNetContentFragment.java - 所有片段的基础,应该显示 "network error" 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 - base Activity,通过改变 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();
    }

}

完整示例位于 https://github.com/relativizt/android-network-error-ui