Home » Android » android – SwipeRefreshLayout refresh animation doesn't stop

android – SwipeRefreshLayout refresh animation doesn't stop

Posted by: admin May 14, 2020 Leave a comment

Questions:

I’ve implemented a fragment which has a SwipeRefreshLayout as content view. Refresh animation is triggered at onRefresh but it never stops even if setRefreshing is set to false after retrieving the data from server.

    @Override
public void onRefresh() {
    handler.post(refreshing);
}


private final Runnable refreshing = new Runnable(){
    public void run(){
        try {
            if(isRefreshing()){
                handler.postDelayed(this, 1000);
            }else{
                swipeLayout.setRefreshing(false);
                mainActivity.forceUpdate();
                setLayout();
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
};

private boolean isRefreshing(){
    return swipeLayout.isRefreshing();
}
How to&Answers:

well, of course it’s not stopping to refresh, look at your loop.

if(isRefreshing()){
    handler.postDelayed(this, 1000);
}else{
    swipeLayout.setRefreshing(false);
    mainActivity.forceUpdate();
    setLayout();
}

basically you are never stopping it,
the “swipeLayout.setRefreshing(false);”
is never called, since the condition it needs is (isRefreshing()) to be false, so it doesn’t make any sense, you will always get a true value from “isRefreshing()” since you’re never telling it to stop.
setRefreshing to false based on the boolean value of isRefreshing is wrong in my opinion, you shouldn’t rely on it, you should be the one to decide when you want to stop the refresh state.

usually PullToRefresh is used to get new data from server.
so basically I would recommend inserting this check right where you get an answer from your server :

if (swipeLayout.isRefreshing()) {
     swipeLayout.setRefreshing(false);
}

because once you get your new data from the server, that’s when you need to stop refreshing.

EDIT – added a full code example

protected SwipeRefreshLayout.OnRefreshListener mOnRefreshListener = new SwipeRefreshLayout.OnRefreshListener() {
    @Override
    public void onRefresh() {
        retrieveDocuments();
    }
};

public void retrieveDocuments() {
//some code, server call

//onCompletion is your server response with a success
@Override
public void onCompletion(String result) {

    if (mSwipeRefreshLayout.isRefreshing()) {
       mSwipeRefreshLayout.setRefreshing(false);
    }
}

}

Answer:

This will remove the animation :

mSwipeRefreshLayout.setRefreshing(false);

Answer:

Use setRefreshing(false) in the UI thread.

Try this:

Handler mHandler = new Handler();//In UI Thread

mHandler.postDelayed(new Runnable() {
    @Override
    public void run() {
        swipeLayout.setRefreshing(isRefreshing);
    }
}, delayTime);

Answer:

In my case I did

mSwipeRefreshLayout.post(new Runnable() {
                @Override
                public void run() {
                    mSwipeRefreshLayout.setRefreshing(true);
                }
            });

twice.
Then, it is not removed by

mSwipeRefreshLayout.setRefreshing(false);

Answer:

if you want to stop loading animation when page is loaded then you have to find first that when page is completely loaded in Webview.

Here is Complete code for load a page in Webview and then stop loading animation after complete page loading.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_web_view);


    final WebView wvSocialMediaPage = findViewById(R.id.wv_social_media_page);
    wvSocialMediaPage.setWebViewClient(new CustomWebViewClient());
    WebSettings webSetting = wvSocialMediaPage.getSettings();
    webSetting.setJavaScriptEnabled(true);
    webSetting.setDisplayZoomControls(true);
    wvSocialMediaPage.loadUrl("https://facebook.com");

    swipeRefreshLayout = (SwipeRefreshLayout) this.findViewById(R.id.swipe_container);
    swipeRefreshLayout.setOnRefreshListener(
            new SwipeRefreshLayout.OnRefreshListener() {
                @Override
                public void onRefresh() {
                    wvSocialMediaPage.reload();
                }
            }
    );
}



    private class CustomWebViewClient extends WebViewClient {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        view.loadUrl(url);
        return true;
    }

    @Override
    public void onPageFinished(WebView view, String url) {
        swipeRefreshLayout.setRefreshing(false);
    }
}

onPageFinished will find when page is loaded Successfully then stop animation.

Answer:

Make sure your listener is set.

mSwipeRefreshLayout = findViewById(R.id.swiperefresh);
mSwipeRefreshLayout.setOnRefreshListener(this); // Important

Answer:

Don’t like Listeners. I do think if you are coding in c# – you have to follow its paradigms. One of those is events. MvxSwipeRefreshLayout has event called Refresh.
And what you can do in its handler is to do some stuff that takes some time, like await for it, and then set Refreshing to false

    private async void SwipeToRefreshControl_Refresh(object sender, EventArgs e)
    {
        await ...some stuff here...
        (sender as MvxSwipeRefreshLayout).Refreshing = false;
    }

Answer:

If you use Kotlin, you can do this with Coroutines.

Where binding.dashboardRefresh is my SwipeRefreshLayout.

    //Refresh the info on Swipe-Refresh
    binding.dashboardRefresh.run {
        setOnRefreshListener {
            menuViewModel.getFields()
            val workerScope = CoroutineScope(Dispatchers.IO)
            workerScope.launch {
                delay(3000)
                isRefreshing = false
            }
        }
    }