D.madushanka
D.madushanka

Reputation: 563

Snackbar in fragments gives IllegalArgumentException: No suitable parent found from the given view

I my app I have two tabs. For tabs I use fragments. Each tab has a network call using Volley. For volley error I am using Snackbar to show the error. My problem is, the Snackbar is working well if I am in that particular fragment while the error is triggering. If I go back before the error trigger this error coming.

Logcat..

12-21 09:11:18.782 3707-3707/com.dushanmadushanka.slicdashboard.slicdashboard E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.dushanmadushanka.slicdashboard.slicdashboard, PID: 3707
    java.lang.IllegalArgumentException: No suitable parent found from the given view. Please provide a valid view.
        at android.support.design.widget.Snackbar.make(Snackbar.java:181)
        at com.dushanmadushanka.slicdashboard.slicdashboard.other.VolleyErrorHandle.handleVolleyErrorThree(VolleyErrorHandle.java:102)
        at com.dushanmadushanka.slicdashboard.slicdashboard.fragment.general.GeneralRegionalFragment$4.onErrorResponse(GeneralRegionalFragment.java:288)
        at com.android.volley.Request.deliverError(Request.java:617)
        at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:104)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5254)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

Fragment...

    @Override
        public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            // Inflate the layout for this fragment
            final View lView = inflater.inflate(R.layout.fragment_life_regional, container, false);

getTableJsonData(1, AppConfig.URL_GET, 1, lView);

    return lView;
    }

Method...

private void getTableJsonData(int currentMonth, String mUrl, int screenType, final View lView) {

    StringRequest stringRequest = new StringRequest(Request.Method.GET, newUrl, new Response.Listener<String>() {
        @Override
        public void onResponse(String response) {


        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            if (requestQueue != null) {
                myList.clear();
                lrAdapter.setJsonData(myList);
                VolleyErrorHandle.handleVolleyErrorThree(error, progressBar, lView.findViewById(R.id.fragment_life_region_layout));
            }
        }
    });
    //AppController.getInstance().addToRequestQueue(stringRequest, TAG_REQ);
    requestQueue.add(stringRequest);
    stringRequest.setRetryPolicy(new DefaultRetryPolicy(15 * 1000, 1,
            DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
}

Snackbar....

public static void handleVolleyErrorThree(VolleyError error, ProgressBar p, View view) {
    if (error instanceof TimeoutError || error instanceof NoConnectionError) {
        Snackbar snackbar = Snackbar.make(view, "Please connect to the network!", Snackbar.LENGTH_LONG);
        View snackbarView = snackbar.getView();
        TextView textView = snackbarView.findViewById(android.support.design.R.id.snackbar_text);
        textView.setTextColor(Color.WHITE);
        snackbarView.setBackgroundColor(Color.RED);
        snackbar.show();
    } else if (error instanceof AuthFailureError) {
        Snackbar snackbar = Snackbar.make(view, "Authentication error!", Snackbar.LENGTH_LONG);
        View snackbarView = snackbar.getView();
        TextView textView = snackbarView.findViewById(android.support.design.R.id.snackbar_text);
        textView.setTextColor(Color.WHITE);
        snackbarView.setBackgroundColor(Color.RED);
        snackbar.show();
    } else if (error instanceof ServerError) {
        Snackbar snackbar = Snackbar.make(view, "No data!", Snackbar.LENGTH_LONG);
        View snackbarView = snackbar.getView();
        TextView textView = snackbarView.findViewById(android.support.design.R.id.snackbar_text);
        textView.setTextColor(Color.WHITE);
        snackbarView.setBackgroundColor(Color.RED);
        snackbar.show();
    } else if (error instanceof NetworkError) {
        Snackbar snackbar = Snackbar.make(view, "Network error!", Snackbar.LENGTH_LONG);
        View snackbarView = snackbar.getView();
        TextView textView = snackbarView.findViewById(android.support.design.R.id.snackbar_text);
        textView.setTextColor(Color.WHITE);
        snackbarView.setBackgroundColor(Color.RED);
        snackbar.show();
    } else if (error instanceof ParseError) {
        Snackbar snackbar = Snackbar.make(view, "Database connection error!", Snackbar.LENGTH_LONG);
        View snackbarView = snackbar.getView();
        TextView textView = snackbarView.findViewById(android.support.design.R.id.snackbar_text);
        textView.setTextColor(Color.WHITE);
        snackbarView.setBackgroundColor(Color.RED);
        snackbar.show();
    }
    p.setVisibility(View.GONE);
}

Upvotes: 4

Views: 4330

Answers (3)

Ziyaad Shiraz
Ziyaad Shiraz

Reputation: 341

I have found out why this problem occurs, it comes when you are using interfaces to communicate the results of an async call such as making a network request. When you navigate from one tab, it's views are rendered invalid (destroyed). But when the async call finally invokes an interface you defined in the tab you navigated from, the view you provided for your snack bar will no longer be valid, hence it throws an error.

Possible solutions:

Cancel all activities that can invoke a callback in a view you navigated from

Upvotes: 0

ישו אוהב אותך
ישו אוהב אותך

Reputation: 29783

You can try using Activity content view as your parameter when calling SnackBar, something like this:

View view = getActivity().findViewById(android.R.id.content);

Snackbar snackbar = Snackbar.make(view, "Please connect to the network!", Snackbar.LENGTH_LONG);
...
snackbar.show();

Upvotes: 3

Vivek Mishra
Vivek Mishra

Reputation: 5705

Seems like you have defined your lView variable twice in your code. You are using a local final variable lView in your onCreateView() method and trying to pass that same view in your snackbar method. So try passing a valid view in your method and it should work.

final View lView = inflater.inflate(R.layout.fragment_life_regional, container, false)

This is your local variable and then you are trying to access it in your handle volley error method call like this

VolleyErrorHandle.handleVolleyErrorThree(error, progressBar, lView.findViewById(R.id.fragment_life_region_layout));

In the above code lView should be null as the the first one is a local variable and will not be accessible in your second method.

Upvotes: 0

Related Questions