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

偶尔善良 提交于 2020-01-13 19:09:09

问题


I have Navigation Drawer in my application with several Fragments and few new Activity also apart from main application flow.

  • Current Functionality
    For navigating to each Fragment, Network is required and in case of any network error, I used to show Dialog. User needs to click on "OK" button and again go back to navigation drawer to retry.
  • New Approach I am trying
    User should be shown and error screen similar to LinkedIn android app with option to retry.

As inner Fragments and handling call back can be cumbersome, how to handle this situation efficiently?
For individual Activities this can be achieved easily, but worried about the Navigation Drawer and inner Fragments.
Any suggestions?


回答1:


Make this error layout hidden in this fragment. When there is any network error then change its visibility to VISIBLE. and in this hidden layout add a button to recall same method to check network connection etc.

Let say you have fragment xml like - fragment -
Relative Layout consisting - 1. -All layouts (VISIBLE) & 2. -Hidden network error layout with a button (GONE)

When there is network error then change 1. 's visibility to - GONE and 2.'s visibility to VISIBLE

and on retry button call -

checkNetworkConnectionCall(); 

I hope this will solve you problem.




回答2:


You can place some ContentFragment in a FrameLayout, then replace with a NetworkDisconnectedFragment when the network disconnects. This would require the button to a call the callback, then when reconnected, replace the NetworkDisconnectedFragment with the old ContentFragment in the callback implementation.




回答3:


You can include this UI in each fragment and create a BaseFragment which will be extended by every fragment in nav drawer.

Write a method in that base fragment that will do the need full logic of changing the UI.

And whenever you detect a network failure just blindly call that method from base fragment there.




回答4:


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



来源:https://stackoverflow.com/questions/36054212/best-approach-to-show-network-error-in-android-in-android-with-tap-to-retry-opti

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!