Lok Lok - 5 months ago 70
Android Question

Implementing Swipe refresh for RecyclerView in android

I want to refresh the

RecyclerView
each time I swipe down. So I use
SwipeRefreshLayout
but now also I am not able to refresh my
RecyclerView
.
Below is the code that I had written:

Below is my XML file named:fragment_static.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:id="@+id/container"
android:layout_height="match_parent">

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

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


Below is my java file named:StaticFragment.java

public class StaticFragment extends Fragment {
private SwipeRefreshLayout mSwipeRefreshLayout;
RecyclerView recyclerView ;
private List<String> fileList = new ArrayList<String>();
private FileAdapter mAdapter ;

public StaticFragment() {
// Required empty public constructor
}

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

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

mSwipeRefreshLayout = (SwipeRefreshLayout) v.findViewById(R.id.container);
mSwipeRefreshLayout.setColorSchemeColors(Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW);
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
Toast.makeText(getContext(), "Refresh", Toast.LENGTH_SHORT).show();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Fragment frg = null;
frg = getFragmentManager().findFragmentByTag("Marker");
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.detach(frg);
ft.attach(frg);
ft.commit();
mSwipeRefreshLayout.setRefreshing(false);
}
}, 2000);
}
});


recyclerView = (RecyclerView)v.findViewById(R.id.recycler_view);
mAdapter = new FileAdapter(fileList);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getContext().getApplicationContext());

recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(mAdapter);

recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getContext(), recyclerView, new ClickListener() {

@Override
public void onClick(View view, int position) {
Intent i = new Intent(getContext(),GraphActivityStatic.class);
i.putExtra("file_name",fileList.get(position));
startActivity(i);
}

@Override
public void onLongClick(View view, int position) {

}
}));

prepareFileData();
return v;
}

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

private void prepareFileData() {
File dir = new File(Environment.getExternalStorageDirectory(),"/PulseData/");
if(!dir.exists())
dir.mkdir();
int position = 0;
fileList.clear();
for (File f : dir.listFiles()) {
if (f.isFile() && f.toString().contains(".txt")) {
fileList.add(f.getName());
mAdapter.notifyItemInserted(position++);
}
}

}



public interface ClickListener {
void onClick(View view, int position);

void onLongClick(View view, int position);
}

public static class RecyclerTouchListener implements RecyclerView.OnItemTouchListener {

private GestureDetector gestureDetector;
private StaticFragment.ClickListener clickListener;

public RecyclerTouchListener(Context context, final RecyclerView recyclerView, final StaticFragment.ClickListener clickListener) {
this.clickListener = clickListener;
gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}

@Override
public void onLongPress(MotionEvent e) {
View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (child != null && clickListener != null) {
clickListener.onLongClick(child, recyclerView.getChildPosition(child));
}
}
});
}

@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {

View child = rv.findChildViewUnder(e.getX(), e.getY());
if (child != null && clickListener != null && gestureDetector.onTouchEvent(e)) {
clickListener.onClick(child, rv.getChildPosition(child));
}
return false;
}

@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}

@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

}
}
}


It is giving me error:

FATAL EXCEPTION: main
java.lang.NullPointerException
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:726)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1617)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:517)
at android.os.Handler.handleCallback(Handler.java:605)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4424)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:817)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:584)
at dalvik.system.NativeStart.main(Native Method)

Answer

The SwipeRefresh don't refresh/reload automatic. You need to add some logic into your function. You don't need and isn't a good pratice use delay (it's only for examples and tests).

mSwipeRefreshLayout.setOnRefreshListener(new    SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                // Do some logic
                // if (refresh is ok)
                Toast.makeText(getContext(), "Refresh", Toast.LENGTH_SHORT).show();
            }
         });

for example you can put all code that you want to reload inside a bind and call the bind inside SwipeListner:

function void bindMyReclyclerView(){
// bind here your recyclerView
}

mSwipeRefreshLayout.setOnRefreshListener(new    SwipeRefreshLayout.OnRefreshListener() {
                @Override
                public void onRefresh() {
                    bindMyRecyclerView();
                    Toast.makeText(getContext(), "Refresh", Toast.LENGTH_SHORT).show();
                }
             });

I've done some similar in my app, take look at This class on GitHub.

You can reload all activity too, but I don't recommend this! (But you can use for tests)

mSwipeRefreshLayout.setOnRefreshListener(new    SwipeRefreshLayout.OnRefreshListener() {
                    @Override
                    public void onRefresh() {
                        finish();
                        startActivity(getIntent());
                        Toast.makeText(getContext(), "Refresh", Toast.LENGTH_SHORT).show();
                    }
                 });
Comments