0

Data is not added to List. The program gets data from a GraphQL server and filter it through a switch statements, then appends it to the corresponding list. However, the list is empty if accessed outside the switch statement. If you print one of the list in the switch statement, it will print correctly, however if you print it in the getter functions, it will not return anything.

What is wrong with it? The scope? I tried putting the initialization in a few places like on the same function or on the constructor however the result is the same.

package sukebei.anilog.data.source.AniList;

import android.util.Log;

import com.apollographql.apollo.ApolloCall;
import com.apollographql.apollo.ApolloClient;
import com.apollographql.apollo.api.Response;
import com.apollographql.apollo.exception.ApolloException;

import org.jetbrains.annotations.NotNull;

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

import okhttp3.OkHttpClient;

import AniList.UserMediaQuery;
import AniList.UserMediaQuery.Data;
import AniList.type.MediaType;

/*  Data Received Example

[
    Entry {
        __typename = MediaList, 
        progress = 0, 
        progressVolumes = null, 
        score = 0.0, 
        status = PLANNING, 
        notes = null, 
        repeat = 0, 
        media = Media {
            __typename = Media, 
            chapters = null, 
            volumes = null, 
            idMal = 17082, 
            episodes = 12, 
            title = Title {
                __typename = MediaTitle, romaji = Aiura
            }
        }
    }, 
    Entry {
        __typename = MediaList, 
        progress = 0, 
        progressVolumes = null, 
        score = 0.0, 
        status = PLANNING, 
        notes = null, 
        repeat = 0, 
        media = Media {
            __typename = Media, 
            chapters = null, 
            volumes = null, 
            idMal = 33218, 
            episodes = 1, 
            title = Title {
            __typename = MediaTitle, 
            romaji = Kimi no Koe wo Todoketai
            }
        }
    }
]
*/


public class AniList {
    private static final String BASE_URL = "https://graphql.anilist.co";

    private List<UserMediaQuery.Entry> planningMedia = new ArrayList<UserMediaQuery.Entry>();
    private List<UserMediaQuery.Entry> currentMedia = new ArrayList<UserMediaQuery.Entry>();
    private List<UserMediaQuery.Entry> completedMedia = new ArrayList<UserMediaQuery.Entry>();
    private List<UserMediaQuery.Entry> droppedMedia = new ArrayList<UserMediaQuery.Entry>();
    private List<UserMediaQuery.Entry> pausedMedia = new ArrayList<UserMediaQuery.Entry>();
    private List<UserMediaQuery.Entry> repeatingMedia = new ArrayList<UserMediaQuery.Entry>();

    private OkHttpClient okHttpClient;
    private ApolloClient apolloClient;

    public AniList() {
        okHttpClient = new OkHttpClient.Builder().build();
        apolloClient = ApolloClient.builder()
            .serverUrl(BASE_URL)
            .okHttpClient(okHttpClient)
            .build();
    }

    public void loadUserData(String username, MediaType mediaType) {

        UserMediaQuery mediaQuery = UserMediaQuery.builder()
                                        .username(username)
                                        .type(mediaType)
                                        .build();

        apolloClient.query(mediaQuery).enqueue(new ApolloCall.Callback<Data>() {
                @Override public void onResponse(@NotNull Response<Data> dataResponse) {
                    for (UserMediaQuery.List data : dataResponse.data().userMediaList().lists()) {
                        for (UserMediaQuery.Entry entry: data.entries()) {
                            switch(entry.status()) {
                                case PLANNING:
                                    planningMedia.add(entry);
                                    break;
                                case CURRENT:
                                    currentMedia.add(entry);
                                    break;
                                case COMPLETED:
                                    completedMedia.add(entry);
                                    break;
                                case DROPPED:
                                    droppedMedia.add(entry);
                                    break;
                                case PAUSED:
                                    pausedMedia.add(entry);
                                    break;
                                case REPEATING:
                                    repeatingMedia.add(entry);
                                    break;
                            }
                        }
                    }
                }

                @Override
                public void onFailure(@NotNull ApolloException t) {
                    Log.e("AniList Source", t.getMessage(), t);
                }
            }
        );
    }

    public List getPlanningMedia() {
        return planningMedia;
    }


    public List getCurrentMedia() {
        return currentMedia;
    }


    public List getCompletedMedia() {
        return completedMedia;
    }


    public List getDroppedMedia() {
        return droppedMedia;
    }


    public List getPausedMedia() {
        return pausedMedia;
    }

    public List getRepeatingMedia() {
        return repeatingMedia;
    }
}

This prints the data however when you print it in the getter function it does not print the data.

            for (UserMediaQuery.List data : dataResponse.data().userMediaList().lists()) {
                for (UserMediaQuery.Entry entry: data.entries()) {
                    if (entry.status() == MediaListStatus.PLANNING) {
                        planningMedia.add(entry);
                        Log.d("planning", planningMedia.toString());
                    }
                }
            }
Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
  • Is entry.status() a string type? – Mohamed Mohaideen AH Oct 13 '18 at 09:24
  • no, its a custom STATUS TYPE –  Oct 13 '18 at 09:25
  • Instead of switch try with if loop maybe some conflict in switch statement with strings & may be custom types based on developement requirements. – Mohamed Mohaideen AH Oct 13 '18 at 09:27
  • It didnt work. the if statement –  Oct 13 '18 at 09:33
  • There is any error or still your list is empty if list is empty check with `entry` object has value.. – Mohamed Mohaideen AH Oct 13 '18 at 09:35
  • It has value. ``` for (UserMediaQuery.List data : dataResponse.data().userMediaList().lists()) { for (UserMediaQuery.Entry entry: data.entries()) { if (entry.status() == MediaListStatus.PLANNING) { planningMedia.add(entry); Log.d("planning", planningMedia.toString()); } } }``` –  Oct 13 '18 at 09:37
  • When I wrote the code above, it prints out all the data, but when you get it from the getter functions, it returns nothing. –  Oct 13 '18 at 09:38
  • Change your return type to List in all getter functions. – Mohamed Mohaideen AH Oct 13 '18 at 09:39
  • @MohamedMohaideenAH This still doesn't fix it but I think it is related to the answer by vizsatiz. The getter executed before the request finished. –  Oct 13 '18 at 11:26

1 Answers1

0

apolloClient.query(mediaQuery).enqueue executes code in async, which means it enqueues the request and so the array list will be empty until the request is being done and is successful from another thread.

You might be using the getter directly without waiting for the callback to finish. If that's the case check out the following possible solutions.

If you are waiting for the request to finish to display something on your UI, you might want to bind the data to UI again by using something like notifyDataSetChanged() in case of RecyclerView for instance. Similarly, if you want to use this data for something else you should probably use a callback mechanism.

Hope this helps !!

vizsatiz
  • 1,933
  • 1
  • 17
  • 36
  • Sorry for the late reply. What is notifyDataSetChanged used for? –  Oct 13 '18 at 11:25
  • That is used for refreshing a `recylerView` if your data has changed, Usually used when you are binding a data list to `View` (https://stackoverflow.com/questions/3669325/notifydatasetchanged-example) – vizsatiz Oct 13 '18 at 12:29
  • Thank your for the answer. Another question, not related so related to the question, is how would you load a data. From what I know right now, it is by having a view to display the data, have an adapter to set the data and have another class to load the data. For this project I am using a GridView. –  Oct 13 '18 at 12:51
  • Check out data binding in Android documentation, they will provide you with detailed explanations. (https://developer.android.com/topic/libraries/data-binding/). Please mark this answer as correct if you find it useful. You can create another question and tag me in if you need further support :) – vizsatiz Oct 13 '18 at 13:11
  • It seems that you are correct on the that it being async. Thank you for the help! –  Oct 13 '18 at 13:13