2

The global idea: Get data from REST API (https://jsonplaceholder.typicode.com/users/1) and then add data to the ListView on my activity layout.

I'm getting data in anonymous class(using retrofit lib), but how can i write it to the ArrayList users (which is class var) to instantiate my ListViewAdapter?

public class CardFragmentUsers extends Fragment implements CardFragment {

    private CardView cardView;
    ArrayList<User> users = new ArrayList<User>();
    UsersListViewAdapter usersListViewAdapter;

    public static Fragment getInstance(int position){
        CardFragmentUsers f = new CardFragmentUsers();
        Bundle args = new Bundle();
        args.putInt("position", position);
        f.setArguments(args);

        return f;
    }

    @SuppressLint("DefaultLocale")
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater,
                             @Nullable ViewGroup container,
                             Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.item_viewpager_users, container, false);

        cardView = (CardView) view.findViewById(R.id.usersCardView);
        cardView.setMaxCardElevation(cardView.getCardElevation() * CardAdapter.MAX_ELEVATION_FACTOR);

        Button usersApplyButton = (Button)view.findViewById(R.id.usersApplyButton);

        usersApplyButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                View parent = (View)view.getParent();

                final TextView userCardviewGuideText = parent.findViewById(R.id.userCardviewGuideText);

                if (InternetConnection.checkConnection(getContext())){

                    ApiService api = RetroClient.getApiService();

                    // getting and filling data
//                    for (int i = 1; i <= 5; i++) {
                        Call<User> call = api.getUser(1);
                        /**
                         * Enqueue Callback will be call when get response...
                         */
                        call.enqueue(new Callback<User>() {
                            @Override
                            public void onResponse(Call<User> call, Response<User> response) {
                                if (response.isSuccessful()){
                                    userCardviewGuideText.setVisibility(View.INVISIBLE);
                                    User user = new User();
                                    user.setName(response.body().getName());
                                    user.setUsername(response.body().getUsername());
                                    users.add(user);
                                }else {
                                    userCardviewGuideText.setVisibility(View.VISIBLE);
                                    Toast.makeText(getActivity(), getString(R.string.smth_went_wrong), Toast.LENGTH_SHORT).show();
                                    return;
                                }
                            }

                            @Override
                            public void onFailure(Call<User> call, Throwable t) {

                            }
                        });

//                    }

                    usersListViewAdapter = new UsersListViewAdapter(parent.getContext(), users);
                    ListView usersListView = (ListView) parent.findViewById(R.id.usersListView);
                    usersListView.setAdapter(usersListViewAdapter);

                }else {
                    Toast.makeText(getActivity(), getString(R.string.no_internet_connection), Toast.LENGTH_SHORT).show();
                    userCardviewGuideText.setVisibility(View.VISIBLE);
                }

            }
        });

        return view;
    }


    public CardView getCardView() {return cardView;}
}
  • 1
    What is the problem? Do you get any compile error or runtime error? – Jack Nov 10 '17 at 13:52
  • how can i write it to the ArrayList users ? you have already write it in anonymous class by this line users.add(user); – Munir Nov 10 '17 at 13:57
  • @Jack Yes, but when i'm at the usersListViewAdapter = new UsersListViewAdapter(parent.getContext(), users); the users are empty (0 users in it) It's because in inner class there are copy of list, not the original ... I'm searching how to fix it –  Nov 10 '17 at 14:00
  • 1
    That's normal. Your call to Retrofit is ASYNCHRONOUS. Means it's not executed at the same time as the rest of the code. So basically you reach the creation of your Adapter before the result of the request is executed. That's why your array is empty. – Eselfar Nov 10 '17 at 14:10

1 Answers1

0

Try this:

Note: I've removed a part of the code that I haven't changed (for clarity purpose).

public class CardFragmentUsers extends Fragment implements CardFragment {

    private CardView cardView;
    ArrayList<User> users = new ArrayList<User>();
    UsersListViewAdapter usersListViewAdapter;
    TextView userCardviewGuideText;

   // ...
   // Your code

    @SuppressLint("DefaultLocale")
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater,
                             @Nullable ViewGroup container,
                             Bundle savedInstanceState) {

        // ...
        // Your code

        // Define the TextView here
        userCardviewGuideText = findViewById(R.id.userCardviewGuideText);

        // Create your adapter outside the listener
        usersListViewAdapter = new UsersListViewAdapter(getContext(), users);
        ListView usersListView = (ListView) view.findViewById(R.id.usersListView);
        usersListView.setAdapter(usersListViewAdapter);

        usersApplyButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                if (InternetConnection.checkConnection(getContext())) {
                    retrieveUserInfoFromApi(); // Using a separate method make the code clearer

                } else {
                    Toast.makeText(getActivity(), getString(R.string.no_internet_connection), Toast.LENGTH_SHORT).show();
                    userCardviewGuideText.setVisibility(View.VISIBLE);
                }

            }
        });

        return view;
    }


    public CardView getCardView() {
        return cardView;
    }

    public void retrieveUserInfoFromApi() {
        ApiService api = RetroClient.getApiService();

        Call<User> call = api.getUser(1);
        /**
         * Enqueue Callback will be call when get response...
         */
        call.enqueue(new Callback<User>() {
            @Override
            public void onResponse(Call<User> call, Response<User> response) {
                if (response.isSuccessful()) {
                    userCardviewGuideText.setVisibility(View.INVISIBLE);
                    User user = new User();
                    user.setName(response.body().getName());
                    user.setUsername(response.body().getUsername());
                    users.add(user);
                    // Notify the adapter that the data have changed
                    usersListViewAdapter.notifyDataSetChanged();
                } else {
                    // ...
                    // Your code
                }
            }

            @Override
            public void onFailure(Call<User> call, Throwable t) {
                // Do something on error
            }
        });
    }
}
Eselfar
  • 3,759
  • 3
  • 23
  • 43
  • Got the idea, changed code, but still nothing in the ListView –  Nov 10 '17 at 14:40
  • Your listView will contain the User only when the onResponse is called. Did you put a breakpoint there to see if the method is called? Then notifyDataSetChanged should be called and your listView updated with the user (as long as the Adapter is correctly implemented) – Eselfar Nov 10 '17 at 14:42
  • And btw, as you're using a ListView, you could use a [listView.setEmptyView(yourTextView)](https://developer.android.com/reference/android/widget/AdapterView.html#setEmptyView(android.view.View)) for the listView to automatically managed the visibility of the `userCardviewGuide` – Eselfar Nov 10 '17 at 14:49
  • 1
    Yes, i did. Now I see that there are users in my usersListViewAdapter, but nothing on the screen, now checking what's wrong with the View ... –  Nov 10 '17 at 15:19