1

I am using Volley for requests and want to add shimmer while data is loading. I can perform it with Handler but I don't know when data will come and can't set exact time.

Here is code in my Fragment. I want to set value false to variable isShimmer and it makes so fast so my shimmer is not running:

String url = "my_url";
JsonArrayRequest getArticleOfTheDayRequest = new JsonArrayRequest(Request.Method.GET, url, null,
            response -> {
                try {
                    for(int i = 0; i < response.length(); i++){
                        JSONObject articleObject = response.getJSONObject(i);
                        int article_id = articleObject.getInt("article_id");
                        String title = articleObject.getString("title");
                        String text = articleObject.getString("text");
                        ArticleOfTheWeek articleOfTheWeek = new ArticleOfTheWeek(article_id, title, text);
                        articleOfTheWeekList.add(articleOfTheWeek);
                    }
                    articleOfTheWeekAdapter = new ArticleOfTheWeekAdapter(getContext(), articleOfTheWeekList);
                    recyclerView.setAdapter(articleOfTheWeekAdapter);
                    articleOfTheWeekAdapter.isShimmer = false;
                    articleOfTheWeekAdapter.notifyDataSetChanged();
                } catch (JSONException e) {
                    e.printStackTrace();
                }

            },
            error -> Log.d("Error.Response", error.getMessage() + " ")
    );

Here code in my adapter:


public boolean isShimmer = true;
int shimmerNumber = 2;

@Override
    public void onBindViewHolder(@NonNull final ArticleOfTheWeekViewHolder holder, int position) {
        final ArticleOfTheWeek articleOfTheWeek = articleOfTheWeekList.get(position);

        if(isShimmer)
        {
            holder.shimmerFrameLayout.startShimmer();
        }else
            {
            holder.shimmerFrameLayout.stopShimmer();
            holder.shimmerFrameLayout.setShimmer(null);

            holder.textViewTitle.setBackground(null);
            holder.textViewTitle.setText(articleOfTheWeek.getTitle());
            holder.textViewDesc.setBackground(null);
            holder.textViewDesc.setText(Html.fromHtml(articleOfTheWeek.getText()));
        }

    }

As you see if I set isShimmer true, shimmer runs infinite. So I can't get a period when all data is loaded to change value of isShimmer

Akram Baratov
  • 143
  • 1
  • 3
  • 13

2 Answers2

3

I've used this library for show shimmer effect while fetching data. First set visibility true to your shimmer layout in your xml file then start shimmer on the start of the activity shimmerViewContainer.startShimmer().

Set shimmerViewContainer.stopShimmer() in your volley method after set data to your adapter in activity file.

As well as stop shimmer on onPause() and onDestroy()

Komal
  • 328
  • 3
  • 15
0

May be it would be easier for you to maintain the shimmer state if you put the shimmer in the parent layout rather than within the adapter layout. I would prefer below approach:


1. Inside the layout of Activity/Fragment

<RelativeLayout>
 <RecyclerView/>
 <FrameLayout 
  android:id="@+id/shimmer_container"> 
 <!-- show hide this FrameLayout container depend on state of data loading/loaded -->
 
  <include layout="@layout/list_shimmer"/>
 </FrameLayout>
</RelativeLayout>

The list_shimmer may be looks like:

<com.facebook.shimmer.ShimmerFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:shimmer_auto_start="true">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <include layout="@layout/just_like_adapter_item_layout" />

        <include layout="@layout/just_like_adapter_item_layout" />

        <!-- repeat until it's enough to fill the screen -->
    </LinearLayout>
</com.facebook.shimmer.ShimmerFrameLayout>

The important property:

app:shimmer_auto_start="true"

So you don't need to start the shimmer programmatically.


2. Activity/Fragment

void initList(List<Data> items) {
  adapter.setItems(items);
  shimmer_container.setVisibility(View.GONE);
}
etomun
  • 134
  • 6
  • You can take the shimmer out from ViewHolder and just load the data normally – etomun Apr 30 '20 at 05:07
  • based on your current code, simply replace **articleOfTheWeekAdapter.isShimmer = false;** with **shimmer_container.setVisibility(View.GONE);** after takeout the shimmer from your adapter – etomun Apr 30 '20 at 05:24