jwf5426 jwf5426 - 5 months ago 105
Java Question

Android: SwipeRefreshLayout will not call OnRefresh()

This community has proven very helpful for my personal and school projects, so I have decided to join. This is my first question. Currently I am building an Android application during my free time in the summer. I am trying to implement a SwipeRefreshLayout in one of my application's fragments, but for unknown reasons, I cannot seem to get my fragment to call the OnRefresh() method when I pull to refresh.

Here is my Java code:

import android.app.Fragment;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.parse.FindCallback;
import com.parse.ParseException;
import com.parse.ParseObject;
import com.parse.ParseQuery;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Notifications extends Fragment implements OnRefreshListener{
private OnFragmentInteractionListener mListener;
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
private SwipeRefreshLayout swipeLayout;
private View view;

public Notifications() {

}

public static Notifications newInstance() {
Notifications fragment = new Notifications();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
accessDataBase();
view = inflater.inflate(R.layout.fragment_notifications, container, false);
swipeLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipeContainer);
swipeLayout.setOnRefreshListener(this);
swipeLayout.setColorSchemeColors(android.R.color.holo_green_dark,
android.R.color.holo_red_dark,
android.R.color.holo_blue_dark,
android.R.color.holo_orange_dark);
return inflater.inflate(R.layout.fragment_notifications, container, false);

}

@Override
public void onRefresh() {
Log.d("Notifications", "onRefresh called from SwipeRefreshLayout");
}

// Used to access my Parse Server database
public void accessDataBase() {
ParseQuery query = new ParseQuery("OurPushes");
query.setCachePolicy(ParseQuery.CachePolicy.CACHE_THEN_NETWORK);
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> objects, ParseException e) {
if (e == null) {
List<String> subject = new ArrayList<>();
List<String> body = new ArrayList<>();
for (ParseObject pushObject : objects) {
if(pushObject.getString("title") != "")
subject.add(pushObject.getString("title"));
else
subject.add("");
if(pushObject.getString("alert") != "")
body.add(pushObject.getString("alert"));
else
body.add("");
}

Collections.reverse(subject);
Collections.reverse(body);

if(getActivity() != null) {
mAdapter = new CustomAdapter(subject, body);
mRecyclerView = (RecyclerView) getActivity().findViewById(R.id.rv);
mLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mAdapter);
}

}
else {
Log.d("Brand", "Error: " + e.getMessage());
}
}
});
}

public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}

@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}

@Override
public void onDetach() {
super.onDetach();
mListener = null;
}

public interface OnFragmentInteractionListener {
void onFragmentInteraction(Uri uri);
}
}


Here is my XML code (fragment_notifications.xml):

<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/swipeContainer"
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.v7.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent" />

</android.support.v4.widget.SwipeRefreshLayout>


And here are the results on my Android Monitor. Notice my Log.d statement within OnRefresh() was not called despite me pulling to refresh on my Android device:

06-16 17:57:13.022 2668-2668/xxxxxxx.xxxxxx W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable
06-16 17:57:13.314 2668-2718/xxxxxxx.xxxxxx D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
06-16 17:57:13.317 2668-2668/xxxxxxx.xxxxxx D/Atlas: Validating map...
06-16 17:57:13.353 2668-2718/xxxxxxx.xxxxxx I/Adreno: EGLInit: QTI Build: 03/04/15, eeab148,
06-16 17:57:13.365 2668-2718/xxxxxxx.xxxxxx I/OpenGLRenderer: Initialized EGL, version 1.4
06-16 17:57:13.366 2668-2718/xxxxxxx.xxxxxx I/Adreno: GetNativeFormatFromQctPixelFormat: Invalid qct format (611)
06-16 17:57:13.366 2668-2718/xxxxxxx.xxxxxx I/Adreno: GetNativeFormatFromQctPixelFormat: Invalid qct format (611)
06-16 17:57:13.366 2668-2718/xxxxxxx.xxxxxx I/Adreno: GetNativeFormatFromQctPixelFormat: Invalid qct format (611)
06-16 17:57:13.366 2668-2718/xxxxxxx.xxxxxx I/Adreno: GetNativeFormatFromQctPixelFormat: Invalid qct format (611)
06-16 17:57:13.366 2668-2718/xxxxxxx.xxxxxx I/Adreno: GetNativeFormatFromQctPixelFormat: Invalid qct format (612)
06-16 17:57:13.366 2668-2718/xxxxxxx.xxxxxx I/Adreno: GetNativeFormatFromQctPixelFormat: Invalid qct format (612)
06-16 17:57:13.366 2668-2718/xxxxxxx.xxxxxx I/Adreno: GetNativeFormatFromQctPixelFormat: Invalid qct format (612)
06-16 17:57:13.366 2668-2718/xxxxxxx.xxxxxx I/Adreno: GetNativeFormatFromQctPixelFormat: Invalid qct format (612)
06-16 17:57:13.373 2668-2718/xxxxxxx.xxxxxx D/OpenGLRenderer: Enabling debug mode 0
06-16 17:57:13.394 2668-2668/xxxxxxx.xxxxxx E/RecyclerView: No adapter attached; skipping layout
06-16 17:57:13.445 2668-2719/xxxxxxx.xxxxxx I/OpenGLRenderer: WorkerThread::readyToRun:hwuiTask1
06-16 17:58:46.962 2668-4140/xxxxxxx.xxxxxx I/OpenGLRenderer: WorkerThread::readyToRun:hwuiTask2


And I know some of you may mention, I know Parse is nearing end life. I am using Parse Server. My parse server is hosted on Heroku, not Parse.com.

Thanks in advance for your help. If you'd like any additional information, please ask.

Answer

In onCreateView you are returning a different view to the one you set up with the OnRefreshListener. Notice you have called inflater.inflate(...) twice, creating two separate Views. Try this instead:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    accessDataBase();
    view = inflater.inflate(R.layout.fragment_notifications, container, false);
    swipeLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipeContainer);
    swipeLayout.setOnRefreshListener(this);
    swipeLayout.setColorSchemeColors(android.R.color.holo_green_dark,
            android.R.color.holo_red_dark,
            android.R.color.holo_blue_dark,
            android.R.color.holo_orange_dark);
    return view;

}